mirror of
https://github.com/SigNoz/signoz.git
synced 2026-04-28 14:40:32 +01:00
Compare commits
61 Commits
chore/base
...
nv/v2-dash
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb6fdd54ec | ||
|
|
64b8ba62da | ||
|
|
7c66df408b | ||
|
|
54049de391 | ||
|
|
9e5678d6b3 | ||
|
|
941016f12c | ||
|
|
500ce85ccb | ||
|
|
a82f4237c8 | ||
|
|
89606b6238 | ||
|
|
db5ce958eb | ||
|
|
c8d3a9a54b | ||
|
|
d1c9864f52 | ||
|
|
637870b1fc | ||
|
|
d46a7e24c9 | ||
|
|
f80b650390 | ||
|
|
2a451e1c31 | ||
|
|
60b6d1d890 | ||
|
|
36f755b232 | ||
|
|
c1b3e3683a | ||
|
|
4c68544b1a | ||
|
|
90d9ab95f9 | ||
|
|
065e712e0c | ||
|
|
50db309ecd | ||
|
|
261bc552b0 | ||
|
|
bab720e98b | ||
|
|
71fef6636b | ||
|
|
fc3cdecbbb | ||
|
|
860fcfa641 | ||
|
|
a090e3a4aa | ||
|
|
6cf73e2ade | ||
|
|
bbcb6a45d6 | ||
|
|
d13934febc | ||
|
|
d5a7b7523d | ||
|
|
5b8984f131 | ||
|
|
6ddc5f1f12 | ||
|
|
64c356b484 | ||
|
|
055968bfad | ||
|
|
1bf0f38ed9 | ||
|
|
97885babe8 | ||
|
|
842125e20a | ||
|
|
6dab35caf8 | ||
|
|
047e9e2001 | ||
|
|
45eaa7db58 | ||
|
|
8a3d894eba | ||
|
|
5239060b53 | ||
|
|
42c6f507ac | ||
|
|
1b695a0b80 | ||
|
|
78e3916aea | ||
|
|
438cfab155 | ||
|
|
69f7617e01 | ||
|
|
a4266fa703 | ||
|
|
44add7b7cd | ||
|
|
feea9e9b36 | ||
|
|
e94767bda8 | ||
|
|
bb10f51cc5 | ||
|
|
4420a7e1fc | ||
|
|
b4bc68c5c5 | ||
|
|
eb9eb317cc | ||
|
|
0b1eb16a42 | ||
|
|
05a4d12183 | ||
|
|
bbaf64c4f0 |
3
.github/workflows/integrationci.yaml
vendored
3
.github/workflows/integrationci.yaml
vendored
@@ -51,6 +51,7 @@ jobs:
|
||||
- role
|
||||
- rootuser
|
||||
- serviceaccount
|
||||
- querier_json_body
|
||||
- ttl
|
||||
sqlstore-provider:
|
||||
- postgres
|
||||
@@ -61,7 +62,7 @@ jobs:
|
||||
- 25.5.6
|
||||
- 25.12.5
|
||||
schema-migrator-version:
|
||||
- v0.142.0
|
||||
- v0.144.3
|
||||
postgres-version:
|
||||
- 15
|
||||
if: |
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/modules/cloudintegration/implcloudintegration"
|
||||
"github.com/SigNoz/signoz/pkg/modules/dashboard"
|
||||
"github.com/SigNoz/signoz/pkg/modules/dashboard/impldashboard"
|
||||
"github.com/SigNoz/signoz/pkg/modules/tag"
|
||||
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||
"github.com/SigNoz/signoz/pkg/modules/rulestatehistory"
|
||||
"github.com/SigNoz/signoz/pkg/modules/serviceaccount"
|
||||
@@ -100,8 +101,8 @@ func runServer(ctx context.Context, config signoz.Config, logger *slog.Logger) e
|
||||
|
||||
return openfgaauthz.NewProviderFactory(sqlstore, openfgaschema.NewSchema().Get(ctx), openfgaDataStore), nil
|
||||
},
|
||||
func(store sqlstore.SQLStore, settings factory.ProviderSettings, analytics analytics.Analytics, orgGetter organization.Getter, queryParser queryparser.QueryParser, _ querier.Querier, _ licensing.Licensing) dashboard.Module {
|
||||
return impldashboard.NewModule(impldashboard.NewStore(store), settings, analytics, orgGetter, queryParser)
|
||||
func(store sqlstore.SQLStore, settings factory.ProviderSettings, analytics analytics.Analytics, orgGetter organization.Getter, queryParser queryparser.QueryParser, _ querier.Querier, _ licensing.Licensing, tagModule tag.Module) dashboard.Module {
|
||||
return impldashboard.NewModule(impldashboard.NewStore(store), store, settings, analytics, orgGetter, queryParser, tagModule)
|
||||
},
|
||||
func(_ licensing.Licensing) factory.ProviderFactory[gateway.Gateway, gateway.Config] {
|
||||
return noopgateway.NewProviderFactory()
|
||||
|
||||
@@ -42,6 +42,7 @@ import (
|
||||
pkgcloudintegration "github.com/SigNoz/signoz/pkg/modules/cloudintegration/implcloudintegration"
|
||||
"github.com/SigNoz/signoz/pkg/modules/dashboard"
|
||||
pkgimpldashboard "github.com/SigNoz/signoz/pkg/modules/dashboard/impldashboard"
|
||||
"github.com/SigNoz/signoz/pkg/modules/tag"
|
||||
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||
"github.com/SigNoz/signoz/pkg/modules/rulestatehistory"
|
||||
"github.com/SigNoz/signoz/pkg/modules/serviceaccount"
|
||||
@@ -144,8 +145,8 @@ func runServer(ctx context.Context, config signoz.Config, logger *slog.Logger) e
|
||||
}
|
||||
return openfgaauthz.NewProviderFactory(sqlstore, openfgaschema.NewSchema().Get(ctx), openfgaDataStore, licensing, onBeforeRoleDelete, dashboardModule), nil
|
||||
},
|
||||
func(store sqlstore.SQLStore, settings factory.ProviderSettings, analytics analytics.Analytics, orgGetter organization.Getter, queryParser queryparser.QueryParser, querier querier.Querier, licensing licensing.Licensing) dashboard.Module {
|
||||
return impldashboard.NewModule(pkgimpldashboard.NewStore(store), settings, analytics, orgGetter, queryParser, querier, licensing)
|
||||
func(store sqlstore.SQLStore, settings factory.ProviderSettings, analytics analytics.Analytics, orgGetter organization.Getter, queryParser queryparser.QueryParser, querier querier.Querier, licensing licensing.Licensing, tagModule tag.Module) dashboard.Module {
|
||||
return impldashboard.NewModule(pkgimpldashboard.NewStore(store), store, settings, analytics, orgGetter, queryParser, querier, licensing, tagModule)
|
||||
},
|
||||
func(licensing licensing.Licensing) factory.ProviderFactory[gateway.Gateway, gateway.Config] {
|
||||
return httpgateway.NewProviderFactory(licensing)
|
||||
@@ -167,7 +168,7 @@ func runServer(ctx context.Context, config signoz.Config, logger *slog.Logger) e
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
azureCloudProviderModule := implcloudprovider.NewAzureCloudProvider()
|
||||
azureCloudProviderModule := implcloudprovider.NewAzureCloudProvider(defStore)
|
||||
cloudProvidersMap := map[cloudintegrationtypes.CloudProviderType]cloudintegration.CloudProviderModule{
|
||||
cloudintegrationtypes.CloudProviderTypeAWS: awsCloudProviderModule,
|
||||
cloudintegrationtypes.CloudProviderTypeAzure: azureCloudProviderModule,
|
||||
|
||||
1611
docs/api/openapi.yml
1611
docs/api/openapi.yml
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,7 @@ func NewAWSCloudProvider(defStore cloudintegrationtypes.ServiceDefinitionStore)
|
||||
return &awscloudprovider{serviceDefinitions: defStore}, nil
|
||||
}
|
||||
|
||||
// TODO: move URL construction logic to cloudintegrationtypes and add unit tests for it.
|
||||
func (provider *awscloudprovider) GetConnectionArtifact(ctx context.Context, account *cloudintegrationtypes.Account, req *cloudintegrationtypes.GetConnectionArtifactRequest) (*cloudintegrationtypes.ConnectionArtifact, error) {
|
||||
baseURL := fmt.Sprintf(cloudintegrationtypes.CloudFormationQuickCreateBaseURL.StringValue(), req.Config.AWS.DeploymentRegion)
|
||||
u, _ := url.Parse(baseURL)
|
||||
|
||||
@@ -2,27 +2,48 @@ package implcloudprovider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/modules/cloudintegration"
|
||||
"github.com/SigNoz/signoz/pkg/types/cloudintegrationtypes"
|
||||
)
|
||||
|
||||
type azurecloudprovider struct{}
|
||||
type azurecloudprovider struct {
|
||||
serviceDefinitions cloudintegrationtypes.ServiceDefinitionStore
|
||||
}
|
||||
|
||||
func NewAzureCloudProvider() cloudintegration.CloudProviderModule {
|
||||
return &azurecloudprovider{}
|
||||
func NewAzureCloudProvider(defStore cloudintegrationtypes.ServiceDefinitionStore) cloudintegration.CloudProviderModule {
|
||||
return &azurecloudprovider{
|
||||
serviceDefinitions: defStore,
|
||||
}
|
||||
}
|
||||
|
||||
func (provider *azurecloudprovider) GetConnectionArtifact(ctx context.Context, account *cloudintegrationtypes.Account, req *cloudintegrationtypes.GetConnectionArtifactRequest) (*cloudintegrationtypes.ConnectionArtifact, error) {
|
||||
panic("implement me")
|
||||
connectionArtifact, err := cloudintegrationtypes.NewAzureConnectionArtifact(account.ID, req.Config.AgentVersion, req.Credentials, req.Config.Azure)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cloudintegrationtypes.ConnectionArtifact{
|
||||
Azure: connectionArtifact,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (provider *azurecloudprovider) ListServiceDefinitions(ctx context.Context) ([]*cloudintegrationtypes.ServiceDefinition, error) {
|
||||
panic("implement me")
|
||||
return provider.serviceDefinitions.List(ctx, cloudintegrationtypes.CloudProviderTypeAzure)
|
||||
}
|
||||
|
||||
func (provider *azurecloudprovider) GetServiceDefinition(ctx context.Context, serviceID cloudintegrationtypes.ServiceID) (*cloudintegrationtypes.ServiceDefinition, error) {
|
||||
panic("implement me")
|
||||
serviceDef, err := provider.serviceDefinitions.Get(ctx, cloudintegrationtypes.CloudProviderTypeAzure, serviceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// override cloud integration dashboard id.
|
||||
for index, dashboard := range serviceDef.Assets.Dashboards {
|
||||
serviceDef.Assets.Dashboards[index].ID = cloudintegrationtypes.GetCloudIntegrationDashboardID(cloudintegrationtypes.CloudProviderTypeAzure, serviceID.StringValue(), dashboard.ID)
|
||||
}
|
||||
|
||||
return serviceDef, nil
|
||||
}
|
||||
|
||||
func (provider *azurecloudprovider) BuildIntegrationConfig(
|
||||
@@ -30,5 +51,56 @@ func (provider *azurecloudprovider) BuildIntegrationConfig(
|
||||
account *cloudintegrationtypes.Account,
|
||||
services []*cloudintegrationtypes.StorableCloudIntegrationService,
|
||||
) (*cloudintegrationtypes.ProviderIntegrationConfig, error) {
|
||||
panic("implement me")
|
||||
sort.Slice(services, func(i, j int) bool {
|
||||
return services[i].Type.StringValue() < services[j].Type.StringValue()
|
||||
})
|
||||
|
||||
var strategies []*cloudintegrationtypes.AzureTelemetryCollectionStrategy
|
||||
|
||||
for _, storedSvc := range services {
|
||||
svcCfg, err := cloudintegrationtypes.NewServiceConfigFromJSON(cloudintegrationtypes.CloudProviderTypeAzure, storedSvc.Config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
svcDef, err := provider.GetServiceDefinition(ctx, storedSvc.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
strategy := svcDef.TelemetryCollectionStrategy.Azure
|
||||
if strategy == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
logsEnabled := svcCfg.IsLogsEnabled(cloudintegrationtypes.CloudProviderTypeAzure)
|
||||
metricsEnabled := svcCfg.IsMetricsEnabled(cloudintegrationtypes.CloudProviderTypeAzure)
|
||||
|
||||
if !logsEnabled && !metricsEnabled {
|
||||
continue
|
||||
}
|
||||
|
||||
entry := &cloudintegrationtypes.AzureTelemetryCollectionStrategy{
|
||||
ResourceProvider: strategy.ResourceProvider,
|
||||
ResourceType: strategy.ResourceType,
|
||||
}
|
||||
|
||||
if metricsEnabled && strategy.Metrics != nil {
|
||||
entry.Metrics = strategy.Metrics
|
||||
}
|
||||
|
||||
if logsEnabled && strategy.Logs != nil {
|
||||
entry.Logs = strategy.Logs
|
||||
}
|
||||
|
||||
strategies = append(strategies, entry)
|
||||
}
|
||||
|
||||
return &cloudintegrationtypes.ProviderIntegrationConfig{
|
||||
Azure: cloudintegrationtypes.NewAzureIntegrationConfig(
|
||||
account.Config.Azure.DeploymentRegion,
|
||||
account.Config.Azure.ResourceGroups,
|
||||
strategies,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -429,9 +429,13 @@ func (module *module) Collect(ctx context.Context, orgID valuer.UUID) (map[strin
|
||||
stats["cloudintegration.aws.connectedaccounts.count"] = awsAccountsCount
|
||||
}
|
||||
|
||||
// NOTE: not adding stats for services for now.
|
||||
// get connected accounts for Azure
|
||||
azureAccountsCount, err := module.store.CountConnectedAccounts(ctx, orgID, cloudintegrationtypes.CloudProviderTypeAzure)
|
||||
if err == nil {
|
||||
stats["cloudintegration.azure.connectedaccounts.count"] = azureAccountsCount
|
||||
}
|
||||
|
||||
// TODO: add more cloud providers when supported
|
||||
// NOTE: not adding stats for services for now.
|
||||
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
@@ -11,12 +11,15 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/modules/dashboard"
|
||||
pkgimpldashboard "github.com/SigNoz/signoz/pkg/modules/dashboard/impldashboard"
|
||||
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||
"github.com/SigNoz/signoz/pkg/modules/tag"
|
||||
"github.com/SigNoz/signoz/pkg/querier"
|
||||
"github.com/SigNoz/signoz/pkg/queryparser"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/dashboardtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/dashboardtypes/dashboardtypesv2"
|
||||
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
@@ -30,9 +33,9 @@ type module struct {
|
||||
licensing licensing.Licensing
|
||||
}
|
||||
|
||||
func NewModule(store dashboardtypes.Store, settings factory.ProviderSettings, analytics analytics.Analytics, orgGetter organization.Getter, queryParser queryparser.QueryParser, querier querier.Querier, licensing licensing.Licensing) dashboard.Module {
|
||||
func NewModule(store dashboardtypes.Store, sqlstore sqlstore.SQLStore, settings factory.ProviderSettings, analytics analytics.Analytics, orgGetter organization.Getter, queryParser queryparser.QueryParser, querier querier.Querier, licensing licensing.Licensing, tagModule tag.Module) dashboard.Module {
|
||||
scopedProviderSettings := factory.NewScopedProviderSettings(settings, "github.com/SigNoz/signoz/ee/modules/dashboard/impldashboard")
|
||||
pkgDashboardModule := pkgimpldashboard.NewModule(store, settings, analytics, orgGetter, queryParser)
|
||||
pkgDashboardModule := pkgimpldashboard.NewModule(store, sqlstore, settings, analytics, orgGetter, queryParser, tagModule)
|
||||
|
||||
return &module{
|
||||
pkgDashboardModule: pkgDashboardModule,
|
||||
@@ -197,6 +200,10 @@ func (module *module) Create(ctx context.Context, orgID valuer.UUID, createdBy s
|
||||
return module.pkgDashboardModule.Create(ctx, orgID, createdBy, creator, data)
|
||||
}
|
||||
|
||||
func (module *module) CreateV2(ctx context.Context, orgID valuer.UUID, createdBy string, creator valuer.UUID, postable dashboardtypesv2.PostableDashboard) (*dashboardtypesv2.Dashboard, error) {
|
||||
return module.pkgDashboardModule.CreateV2(ctx, orgID, createdBy, creator, postable)
|
||||
}
|
||||
|
||||
func (module *module) Get(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*dashboardtypes.Dashboard, error) {
|
||||
return module.pkgDashboardModule.Get(ctx, orgID, id)
|
||||
}
|
||||
|
||||
@@ -313,14 +313,6 @@
|
||||
"name": "react-redux",
|
||||
"message": "[State mgmt] react-redux is deprecated. Migrate to Zustand, nuqs, or react-query."
|
||||
},
|
||||
{
|
||||
"name": "xstate",
|
||||
"message": "[State mgmt] xstate is deprecated. Migrate to Zustand or react-query."
|
||||
},
|
||||
{
|
||||
"name": "@xstate/react",
|
||||
"message": "[State mgmt] @xstate/react is deprecated. Migrate to Zustand or react-query."
|
||||
},
|
||||
{
|
||||
"name": "react",
|
||||
"importNames": [
|
||||
|
||||
5
frontend/knip.json
Normal file
5
frontend/knip.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "https://unpkg.com/knip@5/schema.json",
|
||||
"project": ["src/**/*.ts", "src/**/*.tsx"],
|
||||
"ignore": ["src/api/generated/**/*.ts"]
|
||||
}
|
||||
@@ -63,7 +63,6 @@
|
||||
"@visx/shape": "3.5.0",
|
||||
"@visx/tooltip": "3.3.0",
|
||||
"@vitejs/plugin-react": "5.1.4",
|
||||
"@xstate/react": "^3.0.0",
|
||||
"ansi-to-html": "0.7.2",
|
||||
"antd": "5.11.0",
|
||||
"antd-table-saveas-excel": "2.2.1",
|
||||
@@ -146,7 +145,6 @@
|
||||
"vite": "npm:rolldown-vite@7.3.1",
|
||||
"vite-plugin-html": "3.2.2",
|
||||
"web-vitals": "^0.2.4",
|
||||
"xstate": "^4.31.0",
|
||||
"zod": "4.3.6",
|
||||
"zustand": "5.0.11"
|
||||
},
|
||||
@@ -214,9 +212,9 @@
|
||||
"msw": "1.3.2",
|
||||
"npm-run-all": "latest",
|
||||
"orval": "7.18.0",
|
||||
"oxfmt": "0.46.0",
|
||||
"oxlint": "1.61.0",
|
||||
"oxlint-tsgolint": "0.21.1",
|
||||
"oxfmt": "0.47.0",
|
||||
"oxlint": "1.62.0",
|
||||
"oxlint-tsgolint": "0.22.1",
|
||||
"portfinder-sync": "^0.0.2",
|
||||
"postcss": "8.5.6",
|
||||
"postcss-scss": "4.0.9",
|
||||
@@ -240,9 +238,12 @@
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.(js|jsx|ts|tsx)": [
|
||||
"oxfmt --check",
|
||||
"oxlint --quiet",
|
||||
"oxlint --fix",
|
||||
"oxfmt --write",
|
||||
"sh scripts/typecheck-staged.sh"
|
||||
],
|
||||
"*.(scss|css)": [
|
||||
"stylelint"
|
||||
]
|
||||
},
|
||||
"resolutions": {
|
||||
|
||||
@@ -16,5 +16,6 @@
|
||||
"roles": "Roles",
|
||||
"role_details": "Role Details",
|
||||
"members": "Members",
|
||||
"service_accounts": "Service Accounts"
|
||||
"service_accounts": "Service Accounts",
|
||||
"mcp_server": "MCP Server"
|
||||
}
|
||||
|
||||
@@ -53,5 +53,6 @@
|
||||
"METER": "SigNoz | Meter",
|
||||
"ROLES_SETTINGS": "SigNoz | Roles",
|
||||
"MEMBERS_SETTINGS": "SigNoz | Members",
|
||||
"SERVICE_ACCOUNTS_SETTINGS": "SigNoz | Service Accounts"
|
||||
"SERVICE_ACCOUNTS_SETTINGS": "SigNoz | Service Accounts",
|
||||
"MCP_SERVER": "SigNoz | MCP Server"
|
||||
}
|
||||
|
||||
@@ -16,5 +16,6 @@
|
||||
"roles": "Roles",
|
||||
"role_details": "Role Details",
|
||||
"members": "Members",
|
||||
"service_accounts": "Service Accounts"
|
||||
"service_accounts": "Service Accounts",
|
||||
"mcp_server": "MCP Server"
|
||||
}
|
||||
|
||||
@@ -76,5 +76,6 @@
|
||||
"METER": "SigNoz | Meter",
|
||||
"ROLES_SETTINGS": "SigNoz | Roles",
|
||||
"MEMBERS_SETTINGS": "SigNoz | Members",
|
||||
"SERVICE_ACCOUNTS_SETTINGS": "SigNoz | Service Accounts"
|
||||
"SERVICE_ACCOUNTS_SETTINGS": "SigNoz | Service Accounts",
|
||||
"MCP_SERVER": "SigNoz | MCP Server"
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ describe('getFieldKeys API', () => {
|
||||
const result = await getFieldKeys('traces');
|
||||
|
||||
// Verify the returned structure matches SuccessResponseV2 format
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
httpStatusCode: 200,
|
||||
data: mockSuccessResponse.data.data,
|
||||
});
|
||||
|
||||
@@ -199,7 +199,7 @@ describe('getFieldValues API', () => {
|
||||
const result = await getFieldValues('traces', 'service.name');
|
||||
|
||||
// Verify the returned structure matches SuccessResponseV2 format
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
httpStatusCode: 200,
|
||||
data: expect.objectContaining({
|
||||
values: expect.any(Object),
|
||||
|
||||
@@ -18,10 +18,12 @@ import type {
|
||||
} from 'react-query';
|
||||
|
||||
import type {
|
||||
CreateDashboardV2201,
|
||||
CreatePublicDashboard201,
|
||||
CreatePublicDashboardPathParameters,
|
||||
DashboardtypesPostablePublicDashboardDTO,
|
||||
DashboardtypesUpdatablePublicDashboardDTO,
|
||||
Dashboardtypesv2PostableDashboardDTO,
|
||||
DeletePublicDashboardPathParameters,
|
||||
GetPublicDashboard200,
|
||||
GetPublicDashboardData200,
|
||||
@@ -634,3 +636,88 @@ export const invalidateGetPublicDashboardWidgetQueryRange = async (
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* This endpoint creates a v2-shape dashboard with structured metadata, a typed data tree, and resolved tags.
|
||||
* @summary Create dashboard (v2)
|
||||
*/
|
||||
export const createDashboardV2 = (
|
||||
dashboardtypesv2PostableDashboardDTO: BodyType<Dashboardtypesv2PostableDashboardDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<CreateDashboardV2201>({
|
||||
url: `/api/v2/dashboards`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: dashboardtypesv2PostableDashboardDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getCreateDashboardV2MutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createDashboardV2>>,
|
||||
TError,
|
||||
{ data: BodyType<Dashboardtypesv2PostableDashboardDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createDashboardV2>>,
|
||||
TError,
|
||||
{ data: BodyType<Dashboardtypesv2PostableDashboardDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['createDashboardV2'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof createDashboardV2>>,
|
||||
{ data: BodyType<Dashboardtypesv2PostableDashboardDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
return createDashboardV2(data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type CreateDashboardV2MutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof createDashboardV2>>
|
||||
>;
|
||||
export type CreateDashboardV2MutationBody =
|
||||
BodyType<Dashboardtypesv2PostableDashboardDTO>;
|
||||
export type CreateDashboardV2MutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Create dashboard (v2)
|
||||
*/
|
||||
export const useCreateDashboardV2 = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createDashboardV2>>,
|
||||
TError,
|
||||
{ data: BodyType<Dashboardtypesv2PostableDashboardDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof createDashboardV2>>,
|
||||
TError,
|
||||
{ data: BodyType<Dashboardtypesv2PostableDashboardDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getCreateDashboardV2MutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
787
frontend/src/api/generated/services/spanmapper/index.ts
Normal file
787
frontend/src/api/generated/services/spanmapper/index.ts
Normal file
@@ -0,0 +1,787 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
import type {
|
||||
InvalidateOptions,
|
||||
MutationFunction,
|
||||
QueryClient,
|
||||
QueryFunction,
|
||||
QueryKey,
|
||||
UseMutationOptions,
|
||||
UseMutationResult,
|
||||
UseQueryOptions,
|
||||
UseQueryResult,
|
||||
} from 'react-query';
|
||||
|
||||
import type {
|
||||
CreateSpanMapper201,
|
||||
CreateSpanMapperGroup201,
|
||||
CreateSpanMapperPathParameters,
|
||||
DeleteSpanMapperGroupPathParameters,
|
||||
DeleteSpanMapperPathParameters,
|
||||
ListSpanMapperGroups200,
|
||||
ListSpanMapperGroupsParams,
|
||||
ListSpanMappers200,
|
||||
ListSpanMappersPathParameters,
|
||||
RenderErrorResponseDTO,
|
||||
SpantypesPostableSpanMapperDTO,
|
||||
SpantypesPostableSpanMapperGroupDTO,
|
||||
SpantypesUpdatableSpanMapperDTO,
|
||||
SpantypesUpdatableSpanMapperGroupDTO,
|
||||
UpdateSpanMapperGroupPathParameters,
|
||||
UpdateSpanMapperPathParameters,
|
||||
} from '../sigNoz.schemas';
|
||||
|
||||
import { GeneratedAPIInstance } from '../../../generatedAPIInstance';
|
||||
import type { ErrorType, BodyType } from '../../../generatedAPIInstance';
|
||||
|
||||
/**
|
||||
* Returns all span attribute mapping groups for the authenticated org.
|
||||
* @summary List span attribute mapping groups
|
||||
*/
|
||||
export const listSpanMapperGroups = (
|
||||
params?: ListSpanMapperGroupsParams,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<ListSpanMapperGroups200>({
|
||||
url: `/api/v1/span_mapper_groups`,
|
||||
method: 'GET',
|
||||
params,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getListSpanMapperGroupsQueryKey = (
|
||||
params?: ListSpanMapperGroupsParams,
|
||||
) => {
|
||||
return [`/api/v1/span_mapper_groups`, ...(params ? [params] : [])] as const;
|
||||
};
|
||||
|
||||
export const getListSpanMapperGroupsQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof listSpanMapperGroups>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
params?: ListSpanMapperGroupsParams,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listSpanMapperGroups>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey =
|
||||
queryOptions?.queryKey ?? getListSpanMapperGroupsQueryKey(params);
|
||||
|
||||
const queryFn: QueryFunction<
|
||||
Awaited<ReturnType<typeof listSpanMapperGroups>>
|
||||
> = ({ signal }) => listSpanMapperGroups(params, signal);
|
||||
|
||||
return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listSpanMapperGroups>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type ListSpanMapperGroupsQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof listSpanMapperGroups>>
|
||||
>;
|
||||
export type ListSpanMapperGroupsQueryError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary List span attribute mapping groups
|
||||
*/
|
||||
|
||||
export function useListSpanMapperGroups<
|
||||
TData = Awaited<ReturnType<typeof listSpanMapperGroups>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
params?: ListSpanMapperGroupsParams,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listSpanMapperGroups>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getListSpanMapperGroupsQueryOptions(params, options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
query.queryKey = queryOptions.queryKey;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary List span attribute mapping groups
|
||||
*/
|
||||
export const invalidateListSpanMapperGroups = async (
|
||||
queryClient: QueryClient,
|
||||
params?: ListSpanMapperGroupsParams,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getListSpanMapperGroupsQueryKey(params) },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new span attribute mapping group for the org.
|
||||
* @summary Create a span attribute mapping group
|
||||
*/
|
||||
export const createSpanMapperGroup = (
|
||||
spantypesPostableSpanMapperGroupDTO: BodyType<SpantypesPostableSpanMapperGroupDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<CreateSpanMapperGroup201>({
|
||||
url: `/api/v1/span_mapper_groups`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: spantypesPostableSpanMapperGroupDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getCreateSpanMapperGroupMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createSpanMapperGroup>>,
|
||||
TError,
|
||||
{ data: BodyType<SpantypesPostableSpanMapperGroupDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createSpanMapperGroup>>,
|
||||
TError,
|
||||
{ data: BodyType<SpantypesPostableSpanMapperGroupDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['createSpanMapperGroup'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof createSpanMapperGroup>>,
|
||||
{ data: BodyType<SpantypesPostableSpanMapperGroupDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
return createSpanMapperGroup(data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type CreateSpanMapperGroupMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof createSpanMapperGroup>>
|
||||
>;
|
||||
export type CreateSpanMapperGroupMutationBody =
|
||||
BodyType<SpantypesPostableSpanMapperGroupDTO>;
|
||||
export type CreateSpanMapperGroupMutationError =
|
||||
ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Create a span attribute mapping group
|
||||
*/
|
||||
export const useCreateSpanMapperGroup = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createSpanMapperGroup>>,
|
||||
TError,
|
||||
{ data: BodyType<SpantypesPostableSpanMapperGroupDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof createSpanMapperGroup>>,
|
||||
TError,
|
||||
{ data: BodyType<SpantypesPostableSpanMapperGroupDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getCreateSpanMapperGroupMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* Hard-deletes a mapping group and cascades to all its mappers.
|
||||
* @summary Delete a span attribute mapping group
|
||||
*/
|
||||
export const deleteSpanMapperGroup = ({
|
||||
groupId,
|
||||
}: DeleteSpanMapperGroupPathParameters) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/span_mapper_groups/${groupId}`,
|
||||
method: 'DELETE',
|
||||
});
|
||||
};
|
||||
|
||||
export const getDeleteSpanMapperGroupMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteSpanMapperGroup>>,
|
||||
TError,
|
||||
{ pathParams: DeleteSpanMapperGroupPathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteSpanMapperGroup>>,
|
||||
TError,
|
||||
{ pathParams: DeleteSpanMapperGroupPathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['deleteSpanMapperGroup'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof deleteSpanMapperGroup>>,
|
||||
{ pathParams: DeleteSpanMapperGroupPathParameters }
|
||||
> = (props) => {
|
||||
const { pathParams } = props ?? {};
|
||||
|
||||
return deleteSpanMapperGroup(pathParams);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type DeleteSpanMapperGroupMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof deleteSpanMapperGroup>>
|
||||
>;
|
||||
|
||||
export type DeleteSpanMapperGroupMutationError =
|
||||
ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Delete a span attribute mapping group
|
||||
*/
|
||||
export const useDeleteSpanMapperGroup = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteSpanMapperGroup>>,
|
||||
TError,
|
||||
{ pathParams: DeleteSpanMapperGroupPathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof deleteSpanMapperGroup>>,
|
||||
TError,
|
||||
{ pathParams: DeleteSpanMapperGroupPathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getDeleteSpanMapperGroupMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* Partially updates an existing mapping group's name, condition, or enabled state.
|
||||
* @summary Update a span attribute mapping group
|
||||
*/
|
||||
export const updateSpanMapperGroup = (
|
||||
{ groupId }: UpdateSpanMapperGroupPathParameters,
|
||||
spantypesUpdatableSpanMapperGroupDTO: BodyType<SpantypesUpdatableSpanMapperGroupDTO>,
|
||||
) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/span_mapper_groups/${groupId}`,
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: spantypesUpdatableSpanMapperGroupDTO,
|
||||
});
|
||||
};
|
||||
|
||||
export const getUpdateSpanMapperGroupMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateSpanMapperGroup>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateSpanMapperGroupPathParameters;
|
||||
data: BodyType<SpantypesUpdatableSpanMapperGroupDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateSpanMapperGroup>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateSpanMapperGroupPathParameters;
|
||||
data: BodyType<SpantypesUpdatableSpanMapperGroupDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['updateSpanMapperGroup'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof updateSpanMapperGroup>>,
|
||||
{
|
||||
pathParams: UpdateSpanMapperGroupPathParameters;
|
||||
data: BodyType<SpantypesUpdatableSpanMapperGroupDTO>;
|
||||
}
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
|
||||
return updateSpanMapperGroup(pathParams, data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type UpdateSpanMapperGroupMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof updateSpanMapperGroup>>
|
||||
>;
|
||||
export type UpdateSpanMapperGroupMutationBody =
|
||||
BodyType<SpantypesUpdatableSpanMapperGroupDTO>;
|
||||
export type UpdateSpanMapperGroupMutationError =
|
||||
ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Update a span attribute mapping group
|
||||
*/
|
||||
export const useUpdateSpanMapperGroup = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateSpanMapperGroup>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateSpanMapperGroupPathParameters;
|
||||
data: BodyType<SpantypesUpdatableSpanMapperGroupDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof updateSpanMapperGroup>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateSpanMapperGroupPathParameters;
|
||||
data: BodyType<SpantypesUpdatableSpanMapperGroupDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getUpdateSpanMapperGroupMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* Returns all mappers belonging to a mapping group.
|
||||
* @summary List span mappers for a group
|
||||
*/
|
||||
export const listSpanMappers = (
|
||||
{ groupId }: ListSpanMappersPathParameters,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<ListSpanMappers200>({
|
||||
url: `/api/v1/span_mapper_groups/${groupId}/span_mappers`,
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getListSpanMappersQueryKey = ({
|
||||
groupId,
|
||||
}: ListSpanMappersPathParameters) => {
|
||||
return [`/api/v1/span_mapper_groups/${groupId}/span_mappers`] as const;
|
||||
};
|
||||
|
||||
export const getListSpanMappersQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof listSpanMappers>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
{ groupId }: ListSpanMappersPathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listSpanMappers>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey =
|
||||
queryOptions?.queryKey ?? getListSpanMappersQueryKey({ groupId });
|
||||
|
||||
const queryFn: QueryFunction<Awaited<ReturnType<typeof listSpanMappers>>> = ({
|
||||
signal,
|
||||
}) => listSpanMappers({ groupId }, signal);
|
||||
|
||||
return {
|
||||
queryKey,
|
||||
queryFn,
|
||||
enabled: !!groupId,
|
||||
...queryOptions,
|
||||
} as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listSpanMappers>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type ListSpanMappersQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof listSpanMappers>>
|
||||
>;
|
||||
export type ListSpanMappersQueryError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary List span mappers for a group
|
||||
*/
|
||||
|
||||
export function useListSpanMappers<
|
||||
TData = Awaited<ReturnType<typeof listSpanMappers>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
{ groupId }: ListSpanMappersPathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listSpanMappers>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getListSpanMappersQueryOptions({ groupId }, options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
query.queryKey = queryOptions.queryKey;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary List span mappers for a group
|
||||
*/
|
||||
export const invalidateListSpanMappers = async (
|
||||
queryClient: QueryClient,
|
||||
{ groupId }: ListSpanMappersPathParameters,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getListSpanMappersQueryKey({ groupId }) },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a new mapper to the specified mapping group.
|
||||
* @summary Create a span mapper
|
||||
*/
|
||||
export const createSpanMapper = (
|
||||
{ groupId }: CreateSpanMapperPathParameters,
|
||||
spantypesPostableSpanMapperDTO: BodyType<SpantypesPostableSpanMapperDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<CreateSpanMapper201>({
|
||||
url: `/api/v1/span_mapper_groups/${groupId}/span_mappers`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: spantypesPostableSpanMapperDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getCreateSpanMapperMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createSpanMapper>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: CreateSpanMapperPathParameters;
|
||||
data: BodyType<SpantypesPostableSpanMapperDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createSpanMapper>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: CreateSpanMapperPathParameters;
|
||||
data: BodyType<SpantypesPostableSpanMapperDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['createSpanMapper'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof createSpanMapper>>,
|
||||
{
|
||||
pathParams: CreateSpanMapperPathParameters;
|
||||
data: BodyType<SpantypesPostableSpanMapperDTO>;
|
||||
}
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
|
||||
return createSpanMapper(pathParams, data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type CreateSpanMapperMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof createSpanMapper>>
|
||||
>;
|
||||
export type CreateSpanMapperMutationBody =
|
||||
BodyType<SpantypesPostableSpanMapperDTO>;
|
||||
export type CreateSpanMapperMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Create a span mapper
|
||||
*/
|
||||
export const useCreateSpanMapper = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createSpanMapper>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: CreateSpanMapperPathParameters;
|
||||
data: BodyType<SpantypesPostableSpanMapperDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof createSpanMapper>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: CreateSpanMapperPathParameters;
|
||||
data: BodyType<SpantypesPostableSpanMapperDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getCreateSpanMapperMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* Hard-deletes a mapper from a mapping group.
|
||||
* @summary Delete a span mapper
|
||||
*/
|
||||
export const deleteSpanMapper = ({
|
||||
groupId,
|
||||
mapperId,
|
||||
}: DeleteSpanMapperPathParameters) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/span_mapper_groups/${groupId}/span_mappers/${mapperId}`,
|
||||
method: 'DELETE',
|
||||
});
|
||||
};
|
||||
|
||||
export const getDeleteSpanMapperMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteSpanMapper>>,
|
||||
TError,
|
||||
{ pathParams: DeleteSpanMapperPathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteSpanMapper>>,
|
||||
TError,
|
||||
{ pathParams: DeleteSpanMapperPathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['deleteSpanMapper'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof deleteSpanMapper>>,
|
||||
{ pathParams: DeleteSpanMapperPathParameters }
|
||||
> = (props) => {
|
||||
const { pathParams } = props ?? {};
|
||||
|
||||
return deleteSpanMapper(pathParams);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type DeleteSpanMapperMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof deleteSpanMapper>>
|
||||
>;
|
||||
|
||||
export type DeleteSpanMapperMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Delete a span mapper
|
||||
*/
|
||||
export const useDeleteSpanMapper = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteSpanMapper>>,
|
||||
TError,
|
||||
{ pathParams: DeleteSpanMapperPathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof deleteSpanMapper>>,
|
||||
TError,
|
||||
{ pathParams: DeleteSpanMapperPathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getDeleteSpanMapperMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* Partially updates an existing mapper's field context, config, or enabled state.
|
||||
* @summary Update a span mapper
|
||||
*/
|
||||
export const updateSpanMapper = (
|
||||
{ groupId, mapperId }: UpdateSpanMapperPathParameters,
|
||||
spantypesUpdatableSpanMapperDTO: BodyType<SpantypesUpdatableSpanMapperDTO>,
|
||||
) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/span_mapper_groups/${groupId}/span_mappers/${mapperId}`,
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: spantypesUpdatableSpanMapperDTO,
|
||||
});
|
||||
};
|
||||
|
||||
export const getUpdateSpanMapperMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateSpanMapper>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateSpanMapperPathParameters;
|
||||
data: BodyType<SpantypesUpdatableSpanMapperDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateSpanMapper>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateSpanMapperPathParameters;
|
||||
data: BodyType<SpantypesUpdatableSpanMapperDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['updateSpanMapper'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof updateSpanMapper>>,
|
||||
{
|
||||
pathParams: UpdateSpanMapperPathParameters;
|
||||
data: BodyType<SpantypesUpdatableSpanMapperDTO>;
|
||||
}
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
|
||||
return updateSpanMapper(pathParams, data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type UpdateSpanMapperMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof updateSpanMapper>>
|
||||
>;
|
||||
export type UpdateSpanMapperMutationBody =
|
||||
BodyType<SpantypesUpdatableSpanMapperDTO>;
|
||||
export type UpdateSpanMapperMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Update a span mapper
|
||||
*/
|
||||
export const useUpdateSpanMapper = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateSpanMapper>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateSpanMapperPathParameters;
|
||||
data: BodyType<SpantypesUpdatableSpanMapperDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof updateSpanMapper>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateSpanMapperPathParameters;
|
||||
data: BodyType<SpantypesUpdatableSpanMapperDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getUpdateSpanMapperMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
@@ -1,25 +0,0 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import {
|
||||
GlobalConfigData,
|
||||
GlobalConfigDataProps,
|
||||
} from 'types/api/globalConfig/types';
|
||||
|
||||
const getGlobalConfig = async (): Promise<
|
||||
SuccessResponseV2<GlobalConfigData>
|
||||
> => {
|
||||
try {
|
||||
const response = await axios.get<GlobalConfigDataProps>(`/global/config`);
|
||||
|
||||
return {
|
||||
httpStatusCode: response.status,
|
||||
data: response.data.data,
|
||||
};
|
||||
} catch (error) {
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
}
|
||||
};
|
||||
|
||||
export default getGlobalConfig;
|
||||
@@ -76,10 +76,10 @@ describe('interceptorRejected', () => {
|
||||
}
|
||||
|
||||
const mockAxiosFn = axios as unknown as jest.Mock;
|
||||
expect(mockAxiosFn.mock.calls.length).toBe(1);
|
||||
expect(mockAxiosFn.mock.calls).toHaveLength(1);
|
||||
const retryCallConfig = mockAxiosFn.mock.calls[0][0];
|
||||
expect(Array.isArray(JSON.parse(retryCallConfig.data))).toBe(true);
|
||||
expect(JSON.parse(retryCallConfig.data)).toEqual(arrayPayload);
|
||||
expect(JSON.parse(retryCallConfig.data)).toStrictEqual(arrayPayload);
|
||||
});
|
||||
|
||||
it('should preserve object payload structure when retrying a 401 request', async () => {
|
||||
@@ -112,9 +112,9 @@ describe('interceptorRejected', () => {
|
||||
}
|
||||
|
||||
const mockAxiosFn = axios as unknown as jest.Mock;
|
||||
expect(mockAxiosFn.mock.calls.length).toBe(1);
|
||||
expect(mockAxiosFn.mock.calls).toHaveLength(1);
|
||||
const retryCallConfig = mockAxiosFn.mock.calls[0][0];
|
||||
expect(JSON.parse(retryCallConfig.data)).toEqual(objectPayload);
|
||||
expect(JSON.parse(retryCallConfig.data)).toStrictEqual(objectPayload);
|
||||
});
|
||||
|
||||
it('should handle undefined data gracefully when retrying', async () => {
|
||||
@@ -145,7 +145,7 @@ describe('interceptorRejected', () => {
|
||||
}
|
||||
|
||||
const mockAxiosFn = axios as unknown as jest.Mock;
|
||||
expect(mockAxiosFn.mock.calls.length).toBe(1);
|
||||
expect(mockAxiosFn.mock.calls).toHaveLength(1);
|
||||
const retryCallConfig = mockAxiosFn.mock.calls[0][0];
|
||||
expect(retryCallConfig.data).toBeUndefined();
|
||||
});
|
||||
|
||||
@@ -99,7 +99,7 @@ describe('convertV5ResponseToLegacy', () => {
|
||||
const q = result.payload.data.result[0];
|
||||
expect(q.queryName).toBe('A');
|
||||
expect(q.legend).toBe('{{service.name}}');
|
||||
expect(q.series?.[0]).toEqual(
|
||||
expect(q.series?.[0]).toStrictEqual(
|
||||
expect.objectContaining({
|
||||
labels: { 'service.name': 'adservice' },
|
||||
values: [
|
||||
@@ -186,7 +186,7 @@ describe('convertV5ResponseToLegacy', () => {
|
||||
|
||||
expect(result.payload.data.resultType).toBe('scalar');
|
||||
const [tableEntry] = result.payload.data.result;
|
||||
expect(tableEntry.table?.columns).toEqual([
|
||||
expect(tableEntry.table?.columns).toStrictEqual([
|
||||
{
|
||||
name: 'service.name',
|
||||
queryName: 'A',
|
||||
@@ -202,7 +202,7 @@ describe('convertV5ResponseToLegacy', () => {
|
||||
},
|
||||
{ name: 'F1', queryName: 'F1', isValueColumn: true, id: 'F1' },
|
||||
]);
|
||||
expect(tableEntry.table?.rows?.[0]).toEqual({
|
||||
expect(tableEntry.table?.rows?.[0]).toStrictEqual({
|
||||
data: {
|
||||
'service.name': 'adservice',
|
||||
'A.count()': 606,
|
||||
@@ -257,7 +257,7 @@ describe('convertV5ResponseToLegacy', () => {
|
||||
|
||||
expect(result.payload.data.resultType).toBe('scalar');
|
||||
const [tableEntry] = result.payload.data.result;
|
||||
expect(tableEntry.table?.columns).toEqual([
|
||||
expect(tableEntry.table?.columns).toStrictEqual([
|
||||
{
|
||||
name: 'service.name',
|
||||
queryName: 'A',
|
||||
@@ -267,7 +267,7 @@ describe('convertV5ResponseToLegacy', () => {
|
||||
// Single aggregation: name resolves to legend, id resolves to queryName
|
||||
{ name: '{{service.name}}', queryName: 'A', isValueColumn: true, id: 'A' },
|
||||
]);
|
||||
expect(tableEntry.table?.rows?.[0]).toEqual({
|
||||
expect(tableEntry.table?.rows?.[0]).toStrictEqual({
|
||||
data: {
|
||||
'service.name': 'adservice',
|
||||
A: 580,
|
||||
|
||||
@@ -104,7 +104,7 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
|
||||
const result = prepareQueryRangePayloadV5(props);
|
||||
|
||||
expect(result).toEqual(
|
||||
expect(result).toStrictEqual(
|
||||
expect.objectContaining({
|
||||
legendMap: { A: 'Legend A', F1: 'Formula Legend' },
|
||||
queryPayload: expect.objectContaining({
|
||||
@@ -154,7 +154,10 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
);
|
||||
|
||||
// Legend map combines builder and formulas
|
||||
expect(result.legendMap).toEqual({ A: 'Legend A', F1: 'Formula Legend' });
|
||||
expect(result.legendMap).toStrictEqual({
|
||||
A: 'Legend A',
|
||||
F1: 'Formula Legend',
|
||||
});
|
||||
|
||||
const payload: QueryRangePayloadV5 = result.queryPayload;
|
||||
|
||||
@@ -166,10 +169,10 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
expect(payload.formatOptions?.fillGaps).toBe(true);
|
||||
|
||||
// Variables mapped as { key: { value } }
|
||||
expect(payload.variables).toEqual({
|
||||
svc: { value: 'api' },
|
||||
count: { value: 5 },
|
||||
flag: { value: true },
|
||||
expect(payload.variables).toStrictEqual({
|
||||
svc: { value: 'api', type: undefined },
|
||||
count: { value: 5, type: undefined },
|
||||
flag: { value: true, type: undefined },
|
||||
});
|
||||
|
||||
// Queries include one builder_query and one builder_formula
|
||||
@@ -226,7 +229,7 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
|
||||
const result = prepareQueryRangePayloadV5(props);
|
||||
|
||||
expect(result).toEqual(
|
||||
expect(result).toStrictEqual(
|
||||
expect.objectContaining({
|
||||
legendMap: { A: 'LP' },
|
||||
queryPayload: expect.objectContaining({
|
||||
@@ -255,7 +258,7 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result.legendMap).toEqual({ A: 'LP' });
|
||||
expect(result.legendMap).toStrictEqual({ A: 'LP' });
|
||||
|
||||
const payload: QueryRangePayloadV5 = result.queryPayload;
|
||||
expect(payload.requestType).toBe('time_series');
|
||||
@@ -296,7 +299,7 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
|
||||
const result = prepareQueryRangePayloadV5(props);
|
||||
|
||||
expect(result).toEqual(
|
||||
expect(result).toStrictEqual(
|
||||
expect.objectContaining({
|
||||
legendMap: { Q: 'LC' },
|
||||
queryPayload: expect.objectContaining({
|
||||
@@ -324,7 +327,7 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result.legendMap).toEqual({ Q: 'LC' });
|
||||
expect(result.legendMap).toStrictEqual({ Q: 'LC' });
|
||||
|
||||
const payload: QueryRangePayloadV5 = result.queryPayload;
|
||||
expect(payload.requestType).toBe('scalar');
|
||||
@@ -353,7 +356,7 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
|
||||
const result = prepareQueryRangePayloadV5(props);
|
||||
|
||||
expect(result).toEqual(
|
||||
expect(result).toStrictEqual(
|
||||
expect.objectContaining({
|
||||
legendMap: {},
|
||||
queryPayload: expect.objectContaining({
|
||||
@@ -397,7 +400,7 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
|
||||
const result = prepareQueryRangePayloadV5(props);
|
||||
|
||||
expect(result).toEqual(
|
||||
expect(result).toStrictEqual(
|
||||
expect.objectContaining({
|
||||
legendMap: { A: 'Legend A' },
|
||||
queryPayload: expect.objectContaining({
|
||||
@@ -471,7 +474,7 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
|
||||
const result = prepareQueryRangePayloadV5(props);
|
||||
|
||||
expect(result).toEqual(
|
||||
expect(result).toStrictEqual(
|
||||
expect.objectContaining({
|
||||
legendMap: { A: 'Legend A' },
|
||||
queryPayload: expect.objectContaining({
|
||||
@@ -585,7 +588,7 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
|
||||
const result = prepareQueryRangePayloadV5(props);
|
||||
|
||||
expect(result).toEqual(
|
||||
expect(result).toStrictEqual(
|
||||
expect.objectContaining({
|
||||
legendMap: { A: '{{service.name}}' },
|
||||
queryPayload: expect.objectContaining({
|
||||
@@ -684,7 +687,7 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
|
||||
const result = prepareQueryRangePayloadV5(props);
|
||||
|
||||
expect(result.legendMap).toEqual({ A: 'Legend A' });
|
||||
expect(result.legendMap).toStrictEqual({ A: 'Legend A' });
|
||||
expect(result.queryPayload.compositeQuery.queries).toHaveLength(1);
|
||||
|
||||
const builderQuery = result.queryPayload.compositeQuery.queries.find(
|
||||
@@ -694,7 +697,7 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
|
||||
expect(logSpec.name).toBe('A');
|
||||
expect(logSpec.signal).toBe('logs');
|
||||
expect(logSpec.filter).toEqual({
|
||||
expect(logSpec.filter).toStrictEqual({
|
||||
expression:
|
||||
"service.name = 'payment-service' AND http.status_code >= 400 AND message contains 'error'",
|
||||
});
|
||||
@@ -731,7 +734,9 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
(q) => q.type === 'builder_query',
|
||||
) as QueryEnvelope;
|
||||
const logSpec = builderQuery.spec as LogBuilderQuery;
|
||||
expect(logSpec.filter).toEqual({ expression: 'http.status_code >= 500' });
|
||||
expect(logSpec.filter).toStrictEqual({
|
||||
expression: 'http.status_code >= 500',
|
||||
});
|
||||
});
|
||||
|
||||
it('derives expression from filters when filter is undefined', () => {
|
||||
@@ -775,7 +780,9 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
(q) => q.type === 'builder_query',
|
||||
) as QueryEnvelope;
|
||||
const logSpec = builderQuery.spec as LogBuilderQuery;
|
||||
expect(logSpec.filter).toEqual({ expression: "service.name = 'checkout'" });
|
||||
expect(logSpec.filter).toStrictEqual({
|
||||
expression: "service.name = 'checkout'",
|
||||
});
|
||||
});
|
||||
|
||||
it('prefers filter.expression over filters when both are present', () => {
|
||||
@@ -819,7 +826,9 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
(q) => q.type === 'builder_query',
|
||||
) as QueryEnvelope;
|
||||
const logSpec = builderQuery.spec as LogBuilderQuery;
|
||||
expect(logSpec.filter).toEqual({ expression: "service.name = 'frontend'" });
|
||||
expect(logSpec.filter).toStrictEqual({
|
||||
expression: "service.name = 'frontend'",
|
||||
});
|
||||
});
|
||||
|
||||
it('returns empty expression when neither filter nor filters provided', () => {
|
||||
@@ -853,7 +862,7 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
(q) => q.type === 'builder_query',
|
||||
) as QueryEnvelope;
|
||||
const logSpec = builderQuery.spec as LogBuilderQuery;
|
||||
expect(logSpec.filter).toEqual({ expression: '' });
|
||||
expect(logSpec.filter).toStrictEqual({ expression: '' });
|
||||
});
|
||||
|
||||
it('returns empty expression when filters provided with empty items', () => {
|
||||
@@ -887,6 +896,6 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
(q) => q.type === 'builder_query',
|
||||
) as QueryEnvelope;
|
||||
const logSpec = builderQuery.spec as LogBuilderQuery;
|
||||
expect(logSpec.filter).toEqual({ expression: '' });
|
||||
expect(logSpec.filter).toStrictEqual({ expression: '' });
|
||||
});
|
||||
});
|
||||
|
||||
3
frontend/src/assets/Logos/baseten.svg
Normal file
3
frontend/src/assets/Logos/baseten.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" height="34" viewBox="0 0 131 34">
|
||||
<path fill="currentColor" d="M.36 8.6h16.7v5.6H6.04c-.2 0-.35.16-.35.35v4.9c0 .2.16.35.35.35h11.02v5.6h-5.33c-.2 0-.35.16-.35.35v4.9c0 .2.16.35.35.35h4.98c.2 0 .35-.15.35-.35V25.4h5.34c.2 0 .35-.16.35-.35v-4.9c0-.2-.16-.35-.35-.35h-5.34v-5.6h5.34c.2 0 .35-.16.35-.35v-4.9c0-.2-.16-.35-.35-.35h-5.34V3.35c0-.2-.16-.35-.35-.35H.36c-.2 0-.36.16-.36.35v4.9c0 .2.16.35.36.35ZM44.41 14.7c-.5-.5-1.1-.9-1.76-1.18a5.62 5.62 0 0 0-4.6.17c-.73.37-1.32.91-1.75 1.62h-.17V8.59H34.1v16.83h2.04v-1.81h.17c.21.36.47.67.77.94.31.25.65.48 1.01.67.37.18.77.31 1.18.39a6.2 6.2 0 0 0 3.39-.24 5.36 5.36 0 0 0 3.02-3.1c.29-.75.44-1.62.44-2.6v-.47c0-.96-.16-1.83-.47-2.58-.3-.75-.7-1.4-1.23-1.9v-.01Zm-5.87.66a3.9 3.9 0 0 1 4.34.84c.36.35.64.8.83 1.3.2.5.3 1.07.3 1.7v.47c0 .64-.1 1.23-.3 1.74a3.75 3.75 0 0 1-2.06 2.15 4.27 4.27 0 0 1-3.12-.03 3.86 3.86 0 0 1-2.09-2.2c-.2-.52-.3-1.11-.3-1.75v-.29c0-.62.1-1.2.3-1.7v-.01c.21-.53.5-.99.84-1.36.36-.37.78-.66 1.26-.86ZM97.04 8.59H95v4.86h-2.94v1.86H95v8.17c0 .56.17 1.03.53 1.4.37.35.84.54 1.4.54h4.18v-1.87h-3.5c-.2 0-.33-.05-.43-.15-.1-.1-.14-.27-.14-.49v-7.6h4.65v-1.86h-4.65V8.59ZM114.61 15a5.48 5.48 0 0 0-1.8-1.33 5.6 5.6 0 0 0-2.57-.56 6.17 6.17 0 0 0-4.26 1.7 5.6 5.6 0 0 0-1.72 4.2v.57c0 .9.15 1.75.44 2.5a5.58 5.58 0 0 0 5.5 3.67c1.55 0 2.8-.35 3.72-1.04a5.35 5.35 0 0 0 1.91-2.73l.03-.07-1.94-.52-.02.07c-.11.33-.27.64-.46.94-.17.27-.4.52-.7.74-.28.22-.63.39-1.04.51-.41.13-.9.19-1.46.19a3.8 3.8 0 0 1-2.84-1.05 4.07 4.07 0 0 1-1.1-2.7h9.68v-1.6c0-.54-.11-1.12-.34-1.75a5.04 5.04 0 0 0-1.03-1.74Zm-8.25 3.21a3.8 3.8 0 0 1 1.22-2.25 4.19 4.19 0 0 1 3.99-.7c.44.16.83.38 1.17.66.34.27.62.62.82 1.02.21.38.34.8.38 1.27h-7.58ZM129.09 14.42a4.47 4.47 0 0 0-3.37-1.3c-.93 0-1.73.2-2.4.59-.64.39-1.15.97-1.52 1.74h-.17v-2h-2.04v11.97h2.04v-6.23c0-1.26.32-2.28.95-3.02a3.31 3.31 0 0 1 2.65-1.14c.94 0 1.7.3 2.24.9.56.6.83 1.52.83 2.74v6.75h2.04v-7.13c0-1.71-.42-3.02-1.25-3.87ZM88.1 15a5.48 5.48 0 0 0-1.78-1.33 5.6 5.6 0 0 0-2.58-.56 6.17 6.17 0 0 0-4.27 1.7 5.59 5.59 0 0 0-1.71 4.2v.56c0 .92.14 1.76.44 2.51a5.6 5.6 0 0 0 5.5 3.67c1.55 0 2.8-.35 3.72-1.04a5.36 5.36 0 0 0 1.91-2.73l.03-.07-1.94-.52-.03.07c-.1.32-.26.64-.45.94-.17.27-.4.52-.7.74-.29.21-.64.39-1.05.51-.4.12-.9.19-1.45.19a3.8 3.8 0 0 1-2.85-1.05 4.07 4.07 0 0 1-1.09-2.7h9.68v-1.61c0-.53-.12-1.12-.34-1.74A5.03 5.03 0 0 0 88.1 15Zm-8.24 3.21a3.83 3.83 0 0 1 1.22-2.25 4.2 4.2 0 0 1 3.99-.7c.44.16.83.38 1.16.66.35.27.62.62.83 1.02.2.38.33.8.37 1.27h-7.57ZM73.65 19.42a6.11 6.11 0 0 0-3.23-1.02 6.63 6.63 0 0 1-2.68-.58c-.47-.3-.7-.7-.7-1.25 0-.27.08-.5.21-.7.14-.2.33-.38.56-.52a4.05 4.05 0 0 1 1.78-.42c.85 0 1.54.21 2.06.63.53.41.83 1 .91 1.73l.01.1 1.95-.47-.01-.07c-.07-.45-.22-.91-.45-1.36a3.46 3.46 0 0 0-.94-1.2 4.6 4.6 0 0 0-1.52-.84 6.05 6.05 0 0 0-2.1-.34c-.58 0-1.13.07-1.65.22-.52.14-1 .36-1.43.65-.41.3-.74.66-.99 1.1a2.9 2.9 0 0 0-.37 1.49v.14c0 1.06.38 1.87 1.14 2.42a6.2 6.2 0 0 0 3.24.97c1.18.08 2.04.26 2.56.54.5.28.75.72.75 1.36 0 .6-.25 1.06-.78 1.4-.52.32-1.22.48-2.1.48a3.68 3.68 0 0 1-2.46-.79 3.13 3.13 0 0 1-1.04-2.14v-.09l-1.93.46h-.02v.07a4.4 4.4 0 0 0 3.1 4c.7.24 1.52.36 2.46.36.7 0 1.35-.09 1.93-.27.6-.16 1.12-.4 1.53-.72A3.38 3.38 0 0 0 74.8 22v-.14c0-1.07-.39-1.9-1.14-2.44ZM60.25 23.4c-.1-.1-.14-.27-.14-.49v-9.46h-2.05v1.85h-.16a3.78 3.78 0 0 0-1.61-1.63 4.62 4.62 0 0 0-2.26-.56c-.77 0-1.5.14-2.19.41a5.27 5.27 0 0 0-3.02 3.12c-.29.75-.44 1.63-.44 2.6v.38c0 .99.15 1.87.44 2.63.3.75.7 1.4 1.2 1.93a5.48 5.48 0 0 0 4.05 1.57c.8 0 1.51-.2 2.2-.58.69-.38 1.24-.97 1.63-1.75h.16v.06c0 .56.18 1.03.53 1.4.37.35.85.54 1.41.54h1.36v-1.87h-.68c-.2 0-.34-.05-.43-.15Zm-4.46.13c-.46.2-.97.3-1.52.3a3.68 3.68 0 0 1-2.75-1.09 4.42 4.42 0 0 1-1.05-3.12v-.38c0-.62.1-1.2.29-1.71a3.65 3.65 0 0 1 5-2.17c.47.2.88.49 1.21.86.35.37.62.83.8 1.36.2.5.3 1.08.3 1.7v.3c0 .63-.1 1.23-.3 1.76-.18.5-.45.96-.78 1.33-.33.37-.73.66-1.2.86Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
13
frontend/src/assets/Logos/dbos.svg
Normal file
13
frontend/src/assets/Logos/dbos.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<svg width="109" height="24" viewBox="0 0 109 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_125_22125)">
|
||||
<path d="M0 -2.08616e-07V24H17.9352C22.9911 24 26.0999 21.0858 26.0999 17.04V6.96C26.0999 2.91432 22.9911 -2.08616e-07 17.9352 -2.08616e-07H0ZM6.76413 5.82864H19.1992V18.1714H6.76413V5.82864Z" fill="currentColor"/>
|
||||
<path d="M46.7659 18.6172H35.0824V14.16H46.7659V18.6172ZM46.595 5.38296V9.5658H35.0824V5.38296H46.595ZM50.2846 12.1373V11.5886C52.5734 10.5258 53.7008 8.8458 53.7008 6.13728C53.7008 2.64012 50.9337 0.000116183 45.5361 0.000116183H28.3184V24H45.7752C51.1728 24 53.9399 21.8401 53.9399 18.0685C53.9399 15.0172 52.6418 13.2001 50.2846 12.1373Z" fill="currentColor"/>
|
||||
<path d="M62.397 18.1714H74.8319V5.82864H62.397V18.1714ZM63.6609 24C58.6049 24 55.4961 21.0858 55.4961 17.04V6.96012C55.4961 2.91432 58.6049 0.000116183 63.6609 0.000116183H73.568C78.6238 0.000116183 81.7326 2.91432 81.7326 6.96012V17.04C81.7326 21.0858 78.6238 24 73.568 24H63.6609Z" fill="currentColor"/>
|
||||
<path d="M101.66 15.12L90.8995 14.3658C85.5361 13.9886 83.418 11.1772 83.418 7.47432V6.96012C83.418 2.91432 86.5266 0.000116183 91.5827 0.000116183H100.157C105.214 0.000116183 108.323 2.91432 108.323 6.96012V7.98864H101.968V5.14284H90.2504V8.43432L100.601 9.18864C105.999 9.56568 108.493 12.8572 108.493 16.5257V17.04C108.493 20.7428 105.384 24 100.328 24H91.5827C86.5266 24 83.418 20.7428 83.418 17.04V16.0115H89.7722V18.8572H101.66V15.12Z" fill="currentColor"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_125_22125">
|
||||
<rect width="108.494" height="24" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
1
frontend/src/assets/Logos/opencode.svg
Normal file
1
frontend/src/assets/Logos/opencode.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width='234' height='42' viewBox='0 0 234 42' fill='none' xmlns='http://www.w3.org/2000/svg'><path d='M18 30H6V18H18V30Z' fill='#CFCECD'/><path d='M18 12H6V30H18V12ZM24 36H0V6H24V36Z' fill='#656363'/><path d='M48 30H36V18H48V30Z' fill='#CFCECD'/><path d='M36 30H48V12H36V30ZM54 36H36V42H30V6H54V36Z' fill='#656363'/><path d='M84 24V30H66V24H84Z' fill='#CFCECD'/><path d='M84 24H66V30H84V36H60V6H84V24ZM66 18H78V12H66V18Z' fill='#656363'/><path d='M108 36H96V18H108V36Z' fill='#CFCECD'/><path d='M108 12H96V36H90V6H108V12ZM114 36H108V12H114V36Z' fill='#656363'/><path d='M144 30H126V18H144V30Z' fill='#CFCECD'/><path d='M144 12H126V30H144V36H120V6H144V12Z' fill='#211E1E'/><path d='M168 30H156V18H168V30Z' fill='#CFCECD'/><path d='M168 12H156V30H168V12ZM174 36H150V6H174V36Z' fill='#211E1E'/><path d='M198 30H186V18H198V30Z' fill='#CFCECD'/><path d='M198 12H186V30H198V12ZM204 36H180V6H198V0H204V36Z' fill='#211E1E'/><path d='M234 24V30H216V24H234Z' fill='#CFCECD'/><path d='M216 12V18H228V12H216ZM234 24H216V30H234V36H210V6H234V24Z' fill='#211E1E'/></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -74,7 +74,7 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
background: radial-gradient(circle, #fff 10%, transparent 0);
|
||||
background: radial-gradient(circle, var(--l1-foreground) 10%, transparent 0);
|
||||
background-size: 12px 12px;
|
||||
opacity: 1;
|
||||
|
||||
|
||||
@@ -99,36 +99,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.auth-error-container {
|
||||
.error-content {
|
||||
&__error-code {
|
||||
color: var(--l2-foreground);
|
||||
}
|
||||
|
||||
&__error-message {
|
||||
color: var(--l1-foreground);
|
||||
}
|
||||
|
||||
&__message-badge-label-text {
|
||||
color: var(--l2-foreground);
|
||||
}
|
||||
|
||||
&__message-item {
|
||||
color: var(--l1-foreground);
|
||||
|
||||
&::before {
|
||||
background: var(--l3-background);
|
||||
}
|
||||
}
|
||||
|
||||
&__scroll-hint-text {
|
||||
color: var(--l2-foreground);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes horizontal-shaking {
|
||||
0% {
|
||||
transform: translateX(0);
|
||||
|
||||
@@ -87,23 +87,3 @@
|
||||
background: var(--l3-background);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.auth-footer-content {
|
||||
box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.auth-footer-icon {
|
||||
filter: brightness(0) saturate(100%) invert(25%) sepia(8%) saturate(518%)
|
||||
hue-rotate(192deg) brightness(80%) contrast(95%);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.auth-footer-text {
|
||||
color: var(--text-neutral-light-200);
|
||||
}
|
||||
|
||||
.auth-footer-link-icon {
|
||||
color: var(--text-neutral-light-100);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,28 +143,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.bg-dot-pattern {
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
var(--l3-background) 1px,
|
||||
transparent 1px
|
||||
);
|
||||
background-size: 12px 12px;
|
||||
}
|
||||
|
||||
.auth-page-gradient {
|
||||
background: radial-gradient(
|
||||
ellipse at center top,
|
||||
color-mix(in srgb, var(--primary-background) 12%, transparent) 0%,
|
||||
transparent 60%
|
||||
);
|
||||
opacity: 0.8;
|
||||
filter: blur(200px);
|
||||
|
||||
@media (min-width: 768px) {
|
||||
filter: blur(300px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px solid var(--l1-border);
|
||||
background: linear-gradient(0deg, transparent 0%, transparent 100%), #0b0c0e;
|
||||
|
||||
.ant-card-body {
|
||||
height: 100%;
|
||||
@@ -238,18 +237,7 @@
|
||||
height: 2px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: var(--l1-foreground);
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.celery-task-graph-grid-container {
|
||||
.celery-task-graph-worker-count {
|
||||
background: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.configure-option-Info {
|
||||
border: 1px dashed var(--bg-robin-400);
|
||||
background-color: var(--l1-background);
|
||||
color: var(--l1-foreground);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ function CreateServiceAccountModal(): JSX.Element {
|
||||
SA_QUERY_PARAMS.CREATE_SA,
|
||||
parseAsBoolean.withDefault(false),
|
||||
);
|
||||
const [, setSelectedAccountId] = useQueryState(SA_QUERY_PARAMS.ACCOUNT);
|
||||
|
||||
const { showErrorModal, isErrorModalVisible } = useErrorModal();
|
||||
|
||||
@@ -50,11 +51,12 @@ function CreateServiceAccountModal(): JSX.Element {
|
||||
const { mutate: createServiceAccount, isLoading: isSubmitting } =
|
||||
useCreateServiceAccount({
|
||||
mutation: {
|
||||
onSuccess: async () => {
|
||||
onSuccess: async (response) => {
|
||||
toast.success('Service account created successfully');
|
||||
reset();
|
||||
await setIsOpen(null);
|
||||
await invalidateListServiceAccounts(queryClient);
|
||||
await setSelectedAccountId(response.data.id);
|
||||
},
|
||||
onError: (err) => {
|
||||
const errMessage = convertToApiError(
|
||||
@@ -67,7 +69,7 @@ function CreateServiceAccountModal(): JSX.Element {
|
||||
|
||||
function handleClose(): void {
|
||||
reset();
|
||||
setIsOpen(null);
|
||||
void setIsOpen(null);
|
||||
}
|
||||
|
||||
function handleCreate(values: FormValues): void {
|
||||
|
||||
@@ -77,11 +77,11 @@
|
||||
width: 280px;
|
||||
|
||||
&::placeholder {
|
||||
color: white;
|
||||
color: var(--l1-foreground);
|
||||
}
|
||||
|
||||
&:focus::placeholder {
|
||||
color: rgba($color: #ffffff, $alpha: 0.4);
|
||||
color: rgba($color: var(--l1-foreground), $alpha: 0.4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,42 +113,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.time-options-container {
|
||||
.time-options-item {
|
||||
&.active {
|
||||
background-color: rgba($color: #ffffff, $alpha: 0.2);
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: rgba($color: #ffffff, $alpha: 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: rgba($color: #ffffff, $alpha: 0.3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.timeSelection-input {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
padding: 4px 8px;
|
||||
padding-left: 0px !important;
|
||||
|
||||
input::placeholder {
|
||||
color: var(---bg-ink-300);
|
||||
}
|
||||
|
||||
input:focus::placeholder {
|
||||
color: rgba($color: #000000, $alpha: 0.4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.date-time-popover__footer {
|
||||
border-top: 1px solid var(--l1-border);
|
||||
padding: 8px 14px;
|
||||
@@ -300,34 +264,3 @@
|
||||
background: color-mix(in srgb, var(--bg-robin-200) 8%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.timezone-container {
|
||||
.timezone {
|
||||
background: rgb(179 179 179 / 15%);
|
||||
&__icon {
|
||||
stroke: var(--l1-foreground);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.custom-time-picker {
|
||||
.timeSelection-input {
|
||||
&:hover {
|
||||
border-color: var(--l1-border) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.timezone-badge {
|
||||
background: rgb(179 179 179 / 15%);
|
||||
}
|
||||
|
||||
.time-input-suffix-icon-badge {
|
||||
background: rgb(179 179 179 / 15%);
|
||||
|
||||
&:hover {
|
||||
background: rgb(179 179 179 / 20%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,20 +129,3 @@ $item-spacing: 8px;
|
||||
width: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.timezone-picker {
|
||||
&__search {
|
||||
.search-icon {
|
||||
stroke: var(--l1-foreground);
|
||||
}
|
||||
}
|
||||
}
|
||||
.timezone-name-wrapper {
|
||||
&__selected-icon {
|
||||
.check-icon {
|
||||
stroke: var(--l1-foreground);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ describe.each([
|
||||
const callArgs = mockDownloadExportData.mock.calls[0][0];
|
||||
const query = callArgs.body.compositeQuery.queries[0];
|
||||
expect(query.spec.groupBy).toBeUndefined();
|
||||
expect(query.spec.having).toEqual({ expression: '' });
|
||||
expect(query.spec.having).toStrictEqual({ expression: '' });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -238,7 +238,7 @@ describe.each([
|
||||
expect(mockDownloadExportData).toHaveBeenCalledTimes(1);
|
||||
const callArgs = mockDownloadExportData.mock.calls[0][0];
|
||||
const query = callArgs.body.compositeQuery.queries[0];
|
||||
expect(query.spec.selectFields).toEqual([
|
||||
expect(query.spec.selectFields).toStrictEqual([
|
||||
expect.objectContaining({
|
||||
name: 'http.status',
|
||||
fieldDataType: 'int64',
|
||||
|
||||
@@ -6,39 +6,39 @@ jest.mock('react-dnd', () => ({
|
||||
}));
|
||||
|
||||
describe('Utils testing of DraggableTableRow component', () => {
|
||||
test('Should dropHandler return true', () => {
|
||||
it('Should dropHandler return true', () => {
|
||||
const monitor = {
|
||||
isOver: jest.fn().mockReturnValueOnce(true),
|
||||
} as never;
|
||||
const dropDataTruthy = dropHandler(monitor);
|
||||
|
||||
expect(dropDataTruthy).toEqual({ isOver: true });
|
||||
expect(dropDataTruthy).toStrictEqual({ isOver: true });
|
||||
});
|
||||
|
||||
test('Should dropHandler return false', () => {
|
||||
it('Should dropHandler return false', () => {
|
||||
const monitor = {
|
||||
isOver: jest.fn().mockReturnValueOnce(false),
|
||||
} as never;
|
||||
const dropDataFalsy = dropHandler(monitor);
|
||||
|
||||
expect(dropDataFalsy).toEqual({ isOver: false });
|
||||
expect(dropDataFalsy).toStrictEqual({ isOver: false });
|
||||
});
|
||||
|
||||
test('Should dragHandler return true', () => {
|
||||
it('Should dragHandler return true', () => {
|
||||
const monitor = {
|
||||
isDragging: jest.fn().mockReturnValueOnce(true),
|
||||
} as never;
|
||||
const dragDataTruthy = dragHandler(monitor);
|
||||
|
||||
expect(dragDataTruthy).toEqual({ isDragging: true });
|
||||
expect(dragDataTruthy).toStrictEqual({ isDragging: true });
|
||||
});
|
||||
|
||||
test('Should dragHandler return false', () => {
|
||||
it('Should dragHandler return false', () => {
|
||||
const monitor = {
|
||||
isDragging: jest.fn().mockReturnValueOnce(false),
|
||||
} as never;
|
||||
const dragDataFalsy = dragHandler(monitor);
|
||||
|
||||
expect(dragDataFalsy).toEqual({ isDragging: false });
|
||||
expect(dragDataFalsy).toStrictEqual({ isDragging: false });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
.dropdown-button {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dropdown-button--dark {
|
||||
color: #000;
|
||||
color: var(--l1-foreground);
|
||||
}
|
||||
|
||||
.dropdown-icon {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useState } from 'react';
|
||||
import { EllipsisOutlined } from '@ant-design/icons';
|
||||
import { Button, Dropdown, MenuProps } from 'antd';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
|
||||
import './DropDown.styles.scss';
|
||||
|
||||
@@ -12,8 +11,6 @@ function DropDown({
|
||||
element: JSX.Element[];
|
||||
onDropDownItemClick?: MenuProps['onClick'];
|
||||
}): JSX.Element {
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
const items: MenuProps['items'] = element.map(
|
||||
(e: JSX.Element, index: number) => ({
|
||||
label: e,
|
||||
@@ -35,7 +32,7 @@ function DropDown({
|
||||
>
|
||||
<Button
|
||||
type="link"
|
||||
className={!isDarkMode ? 'dropdown-button--dark' : 'dropdown-button'}
|
||||
className={`dropdown-button`}
|
||||
onClick={(e): void => {
|
||||
e.preventDefault();
|
||||
setDdOpen(true);
|
||||
|
||||
@@ -361,9 +361,9 @@ describe('EditMemberDrawer', () => {
|
||||
|
||||
await user.click(screen.getByRole('button', { name: /delete member/i }));
|
||||
|
||||
expect(
|
||||
await screen.findByText(/are you sure you want to delete/i),
|
||||
).toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByText(/are you sure you want to delete/i),
|
||||
).resolves.toBeInTheDocument();
|
||||
|
||||
const confirmBtns = screen.getAllByRole('button', { name: /delete member/i });
|
||||
await user.click(confirmBtns[confirmBtns.length - 1]);
|
||||
@@ -441,9 +441,9 @@ describe('EditMemberDrawer', () => {
|
||||
|
||||
await user.click(screen.getByRole('button', { name: /revoke invite/i }));
|
||||
|
||||
expect(
|
||||
await screen.findByText(/Are you sure you want to revoke the invite/i),
|
||||
).toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByText(/Are you sure you want to revoke the invite/i),
|
||||
).resolves.toBeInTheDocument();
|
||||
|
||||
const confirmBtns = screen.getAllByRole('button', { name: /revoke invite/i });
|
||||
await user.click(confirmBtns[confirmBtns.length - 1]);
|
||||
|
||||
@@ -64,7 +64,7 @@ export const legend = (id: string, isLonger: boolean): Plugin<ChartType> => ({
|
||||
// li.style.marginTop = '5px';
|
||||
|
||||
li.onclick = (): void => {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
const { type } = chart.config;
|
||||
if (type === 'pie' || type === 'doughnut') {
|
||||
// Pie and doughnut charts only have a single dataset and visibility is per item
|
||||
|
||||
@@ -9,65 +9,65 @@ describe('xAxisConfig for Chart', () => {
|
||||
const start = dayjs();
|
||||
const end = start.add(10, 'millisecond');
|
||||
|
||||
expect(convertTimeRange(start.valueOf(), end.valueOf()).unitName).toEqual(
|
||||
TIME_UNITS.millisecond,
|
||||
);
|
||||
expect(
|
||||
convertTimeRange(start.valueOf(), end.valueOf()).unitName,
|
||||
).toStrictEqual(TIME_UNITS.millisecond);
|
||||
}
|
||||
{
|
||||
const start = dayjs();
|
||||
const end = start.add(10, 'second');
|
||||
|
||||
expect(convertTimeRange(start.valueOf(), end.valueOf()).unitName).toEqual(
|
||||
TIME_UNITS.second,
|
||||
);
|
||||
expect(
|
||||
convertTimeRange(start.valueOf(), end.valueOf()).unitName,
|
||||
).toStrictEqual(TIME_UNITS.second);
|
||||
}
|
||||
{
|
||||
const start = dayjs();
|
||||
const end = start.add(10, 'minute');
|
||||
|
||||
expect(convertTimeRange(start.valueOf(), end.valueOf()).unitName).toEqual(
|
||||
TIME_UNITS.minute,
|
||||
);
|
||||
expect(
|
||||
convertTimeRange(start.valueOf(), end.valueOf()).unitName,
|
||||
).toStrictEqual(TIME_UNITS.minute);
|
||||
}
|
||||
{
|
||||
const start = dayjs();
|
||||
const end = start.add(10, 'hour');
|
||||
|
||||
expect(convertTimeRange(start.valueOf(), end.valueOf()).unitName).toEqual(
|
||||
TIME_UNITS.hour,
|
||||
);
|
||||
expect(
|
||||
convertTimeRange(start.valueOf(), end.valueOf()).unitName,
|
||||
).toStrictEqual(TIME_UNITS.hour);
|
||||
}
|
||||
{
|
||||
const start = dayjs();
|
||||
const end = start.add(10, 'day');
|
||||
|
||||
expect(convertTimeRange(start.valueOf(), end.valueOf()).unitName).toEqual(
|
||||
TIME_UNITS.day,
|
||||
);
|
||||
expect(
|
||||
convertTimeRange(start.valueOf(), end.valueOf()).unitName,
|
||||
).toStrictEqual(TIME_UNITS.day);
|
||||
}
|
||||
{
|
||||
const start = dayjs();
|
||||
const end = start.add(10, 'week');
|
||||
|
||||
expect(convertTimeRange(start.valueOf(), end.valueOf()).unitName).toEqual(
|
||||
TIME_UNITS.week,
|
||||
);
|
||||
expect(
|
||||
convertTimeRange(start.valueOf(), end.valueOf()).unitName,
|
||||
).toStrictEqual(TIME_UNITS.week);
|
||||
}
|
||||
{
|
||||
const start = dayjs();
|
||||
const end = start.add(10, 'month');
|
||||
|
||||
expect(convertTimeRange(start.valueOf(), end.valueOf()).unitName).toEqual(
|
||||
TIME_UNITS.month,
|
||||
);
|
||||
expect(
|
||||
convertTimeRange(start.valueOf(), end.valueOf()).unitName,
|
||||
).toStrictEqual(TIME_UNITS.month);
|
||||
}
|
||||
{
|
||||
const start = dayjs();
|
||||
const end = start.add(10, 'year');
|
||||
|
||||
expect(convertTimeRange(start.valueOf(), end.valueOf()).unitName).toEqual(
|
||||
TIME_UNITS.year,
|
||||
);
|
||||
expect(
|
||||
convertTimeRange(start.valueOf(), end.valueOf()).unitName,
|
||||
).toStrictEqual(TIME_UNITS.year);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@ const testFullPrecisionGetYAxisFormattedValue = (
|
||||
): string => getYAxisFormattedValue(value, format, PrecisionOptionsEnum.FULL);
|
||||
|
||||
describe('getYAxisFormattedValue - none (full precision legacy assertions)', () => {
|
||||
test('large integers and decimals', () => {
|
||||
it('large integers and decimals', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('250034', 'none')).toBe(
|
||||
'250034',
|
||||
);
|
||||
@@ -22,7 +22,7 @@ describe('getYAxisFormattedValue - none (full precision legacy assertions)', ()
|
||||
);
|
||||
});
|
||||
|
||||
test('preserves leading zeros after decimal until first non-zero', () => {
|
||||
it('preserves leading zeros after decimal until first non-zero', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('1.0000234', 'none')).toBe(
|
||||
'1.0000234',
|
||||
);
|
||||
@@ -31,7 +31,7 @@ describe('getYAxisFormattedValue - none (full precision legacy assertions)', ()
|
||||
);
|
||||
});
|
||||
|
||||
test('trims to three significant decimals and removes trailing zeros', () => {
|
||||
it('trims to three significant decimals and removes trailing zeros', () => {
|
||||
expect(
|
||||
testFullPrecisionGetYAxisFormattedValue('0.000000250034', 'none'),
|
||||
).toBe('0.000000250034');
|
||||
@@ -55,7 +55,7 @@ describe('getYAxisFormattedValue - none (full precision legacy assertions)', ()
|
||||
).toBe('0.00000025');
|
||||
});
|
||||
|
||||
test('whole numbers normalize', () => {
|
||||
it('whole numbers normalize', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('1000', 'none')).toBe('1000');
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('99.5458', 'none')).toBe(
|
||||
'99.5458',
|
||||
@@ -68,7 +68,7 @@ describe('getYAxisFormattedValue - none (full precision legacy assertions)', ()
|
||||
);
|
||||
});
|
||||
|
||||
test('strip redundant decimal zeros', () => {
|
||||
it('strip redundant decimal zeros', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('1000.000', 'none')).toBe(
|
||||
'1000',
|
||||
);
|
||||
@@ -78,7 +78,7 @@ describe('getYAxisFormattedValue - none (full precision legacy assertions)', ()
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('1.000', 'none')).toBe('1');
|
||||
});
|
||||
|
||||
test('edge values', () => {
|
||||
it('edge values', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('0', 'none')).toBe('0');
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('-0', 'none')).toBe('0');
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('Infinity', 'none')).toBe('∞');
|
||||
@@ -92,7 +92,7 @@ describe('getYAxisFormattedValue - none (full precision legacy assertions)', ()
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('abc123', 'none')).toBe('NaN');
|
||||
});
|
||||
|
||||
test('small decimals keep precision as-is', () => {
|
||||
it('small decimals keep precision as-is', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('0.0001', 'none')).toBe(
|
||||
'0.0001',
|
||||
);
|
||||
@@ -104,7 +104,7 @@ describe('getYAxisFormattedValue - none (full precision legacy assertions)', ()
|
||||
);
|
||||
});
|
||||
|
||||
test('simple decimals preserved', () => {
|
||||
it('simple decimals preserved', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('0.1', 'none')).toBe('0.1');
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('0.2', 'none')).toBe('0.2');
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('0.3', 'none')).toBe('0.3');
|
||||
@@ -115,7 +115,7 @@ describe('getYAxisFormattedValue - none (full precision legacy assertions)', ()
|
||||
});
|
||||
|
||||
describe('getYAxisFormattedValue - units (full precision legacy assertions)', () => {
|
||||
test('ms', () => {
|
||||
it('ms', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('1500', 'ms')).toBe('1.5 s');
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('500', 'ms')).toBe('500 ms');
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('60000', 'ms')).toBe('1 min');
|
||||
@@ -127,19 +127,19 @@ describe('getYAxisFormattedValue - units (full precision legacy assertions)', ()
|
||||
);
|
||||
});
|
||||
|
||||
test('s', () => {
|
||||
it('s', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('90', 's')).toBe('1.5 mins');
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('30', 's')).toBe('30 s');
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('3600', 's')).toBe('1 hour');
|
||||
});
|
||||
|
||||
test('m', () => {
|
||||
it('m', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('90', 'm')).toBe('1.5 hours');
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('30', 'm')).toBe('30 min');
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('1440', 'm')).toBe('1 day');
|
||||
});
|
||||
|
||||
test('bytes', () => {
|
||||
it('bytes', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('1024', 'bytes')).toBe(
|
||||
'1 KiB',
|
||||
);
|
||||
@@ -149,7 +149,7 @@ describe('getYAxisFormattedValue - units (full precision legacy assertions)', ()
|
||||
);
|
||||
});
|
||||
|
||||
test('mbytes', () => {
|
||||
it('mbytes', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('1024', 'mbytes')).toBe(
|
||||
'1 GiB',
|
||||
);
|
||||
@@ -161,7 +161,7 @@ describe('getYAxisFormattedValue - units (full precision legacy assertions)', ()
|
||||
);
|
||||
});
|
||||
|
||||
test('kbytes', () => {
|
||||
it('kbytes', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('1024', 'kbytes')).toBe(
|
||||
'1 MiB',
|
||||
);
|
||||
@@ -173,7 +173,7 @@ describe('getYAxisFormattedValue - units (full precision legacy assertions)', ()
|
||||
);
|
||||
});
|
||||
|
||||
test('short', () => {
|
||||
it('short', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('1000', 'short')).toBe('1 K');
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('1500', 'short')).toBe(
|
||||
'1.5 K',
|
||||
@@ -201,7 +201,7 @@ describe('getYAxisFormattedValue - units (full precision legacy assertions)', ()
|
||||
);
|
||||
});
|
||||
|
||||
test('percent', () => {
|
||||
it('percent', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('0.15', 'percent')).toBe(
|
||||
'0.15%',
|
||||
);
|
||||
@@ -235,7 +235,7 @@ describe('getYAxisFormattedValue - units (full precision legacy assertions)', ()
|
||||
).toBe('1.005555555595959%');
|
||||
});
|
||||
|
||||
test('ratio', () => {
|
||||
it('ratio', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('0.5', 'ratio')).toBe(
|
||||
'0.5 ratio',
|
||||
);
|
||||
@@ -247,7 +247,7 @@ describe('getYAxisFormattedValue - units (full precision legacy assertions)', ()
|
||||
);
|
||||
});
|
||||
|
||||
test('temperature units', () => {
|
||||
it('temperature units', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('25', 'celsius')).toBe(
|
||||
'25 °C',
|
||||
);
|
||||
@@ -267,13 +267,13 @@ describe('getYAxisFormattedValue - units (full precision legacy assertions)', ()
|
||||
);
|
||||
});
|
||||
|
||||
test('ms edge cases', () => {
|
||||
it('ms edge cases', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('0', 'ms')).toBe('0 ms');
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('-1500', 'ms')).toBe('-1.5 s');
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('Infinity', 'ms')).toBe('∞');
|
||||
});
|
||||
|
||||
test('bytes edge cases', () => {
|
||||
it('bytes edge cases', () => {
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('0', 'bytes')).toBe('0 B');
|
||||
expect(testFullPrecisionGetYAxisFormattedValue('-1024', 'bytes')).toBe(
|
||||
'-1 KiB',
|
||||
@@ -282,7 +282,7 @@ describe('getYAxisFormattedValue - units (full precision legacy assertions)', ()
|
||||
});
|
||||
|
||||
describe('getYAxisFormattedValue - precision option tests', () => {
|
||||
test('precision 0 drops decimal part', () => {
|
||||
it('precision 0 drops decimal part', () => {
|
||||
expect(getYAxisFormattedValue('1.2345', 'none', 0)).toBe('1');
|
||||
expect(getYAxisFormattedValue('0.9999', 'none', 0)).toBe('0');
|
||||
expect(getYAxisFormattedValue('12345.6789', 'none', 0)).toBe('12345');
|
||||
@@ -294,7 +294,7 @@ describe('getYAxisFormattedValue - precision option tests', () => {
|
||||
// with unit
|
||||
expect(getYAxisFormattedValue('4353.81', 'ms', 0)).toBe('4 s');
|
||||
});
|
||||
test('precision 1,2,3,4 decimals', () => {
|
||||
it('precision 1,2,3,4 decimals', () => {
|
||||
expect(getYAxisFormattedValue('1.2345', 'none', 1)).toBe('1.2');
|
||||
expect(getYAxisFormattedValue('1.2345', 'none', 2)).toBe('1.23');
|
||||
expect(getYAxisFormattedValue('1.2345', 'none', 3)).toBe('1.234');
|
||||
@@ -345,7 +345,7 @@ describe('getYAxisFormattedValue - precision option tests', () => {
|
||||
expect(getYAxisFormattedValue('0.123456', 'percent', 4)).toBe('0.1235%'); // approximation
|
||||
});
|
||||
|
||||
test('precision full uses up to DEFAULT_SIGNIFICANT_DIGITS significant digits', () => {
|
||||
it('precision full uses up to DEFAULT_SIGNIFICANT_DIGITS significant digits', () => {
|
||||
expect(
|
||||
getYAxisFormattedValue(
|
||||
'0.00002625429914148441',
|
||||
|
||||
@@ -90,11 +90,11 @@ describe('InviteMembersModal', () => {
|
||||
screen.getByRole('button', { name: /invite team members/i }),
|
||||
);
|
||||
|
||||
expect(
|
||||
await screen.findByText(
|
||||
await expect(
|
||||
screen.findByText(
|
||||
'Please enter valid emails and select roles for team members',
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
).resolves.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows email-only message when email is invalid but role is selected', async () => {
|
||||
@@ -112,9 +112,9 @@ describe('InviteMembersModal', () => {
|
||||
screen.getByRole('button', { name: /invite team members/i }),
|
||||
);
|
||||
|
||||
expect(
|
||||
await screen.findByText('Please enter valid emails for team members'),
|
||||
).toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByText('Please enter valid emails for team members'),
|
||||
).resolves.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows role-only message when email is valid but role is missing', async () => {
|
||||
@@ -130,9 +130,9 @@ describe('InviteMembersModal', () => {
|
||||
screen.getByRole('button', { name: /invite team members/i }),
|
||||
);
|
||||
|
||||
expect(
|
||||
await screen.findByText('Please select roles for team members'),
|
||||
).toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByText('Please select roles for team members'),
|
||||
).resolves.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import cx from 'classnames';
|
||||
import { LogType } from 'components/Logs/LogStateIndicator/LogStateIndicator';
|
||||
import QuerySearch from 'components/QueryBuilderV2/QueryV2/QuerySearch/QuerySearch';
|
||||
import { convertExpressionToFilters } from 'components/QueryBuilderV2/utils';
|
||||
import { FeatureKeys } from 'constants/features';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import { QueryParams } from 'constants/query';
|
||||
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
|
||||
@@ -46,6 +47,7 @@ import {
|
||||
TextSelect,
|
||||
X,
|
||||
} from 'lucide-react';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { Query, TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { DataSource, StringOperators } from 'types/common/queryBuilder';
|
||||
@@ -79,6 +81,10 @@ function LogDetailInner({
|
||||
const [selectedView, setSelectedView] = useState<VIEWS>(selectedTab);
|
||||
|
||||
const [isFilterVisible, setIsFilterVisible] = useState<boolean>(false);
|
||||
const { featureFlags } = useAppContext();
|
||||
const isBodyJsonQueryEnabled =
|
||||
featureFlags?.find((flag) => flag.name === FeatureKeys.BODY_JSON_ENABLED)
|
||||
?.active || false;
|
||||
|
||||
const [filters, setFilters] = useState<TagFilter | null>(null);
|
||||
const [isEdit, setIsEdit] = useState<boolean>(false);
|
||||
@@ -208,11 +214,29 @@ function LogDetailInner({
|
||||
}
|
||||
};
|
||||
|
||||
const logBody = useMemo(() => {
|
||||
if (!isBodyJsonQueryEnabled) {
|
||||
return log?.body || '';
|
||||
}
|
||||
|
||||
try {
|
||||
const json = JSON.parse(log?.body || '');
|
||||
|
||||
if (typeof json?.message === 'string' && json.message !== '') {
|
||||
return json.message;
|
||||
}
|
||||
|
||||
return log?.body || '';
|
||||
} catch (error) {
|
||||
return log?.body || '';
|
||||
}
|
||||
}, [isBodyJsonQueryEnabled, log?.body]);
|
||||
|
||||
const htmlBody = useMemo(
|
||||
() => ({
|
||||
__html: getSanitizedLogBody(log?.body || '', { shouldEscapeHtml: true }),
|
||||
__html: getSanitizedLogBody(logBody || '', { shouldEscapeHtml: true }),
|
||||
}),
|
||||
[log?.body],
|
||||
[logBody],
|
||||
);
|
||||
|
||||
const handleJSONCopy = (): void => {
|
||||
@@ -418,7 +442,7 @@ function LogDetailInner({
|
||||
<div className="log-detail-drawer__log">
|
||||
<Divider type="vertical" className={cx('log-type-indicator', logType)} />
|
||||
<Tooltip
|
||||
title={removeEscapeCharacters(log?.body)}
|
||||
title={removeEscapeCharacters(logBody)}
|
||||
placement="left"
|
||||
mouseLeaveDelay={0}
|
||||
>
|
||||
|
||||
@@ -27,7 +27,7 @@ describe('getLogIndicatorType', () => {
|
||||
expect(getLogIndicatorType(log)).toBe('TRACE');
|
||||
});
|
||||
|
||||
it('severity_text should be used when severity_number is absent ', () => {
|
||||
it('severity_text should be used when severity_number is absent', () => {
|
||||
const log = {
|
||||
date: '2024-02-29T12:34:46Z',
|
||||
timestamp: 1646115296,
|
||||
|
||||
@@ -75,7 +75,7 @@ function OptionsMenu({
|
||||
};
|
||||
|
||||
const handleSearchValueChange = useDebouncedFn((event): void => {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
const value = event?.target?.value || '';
|
||||
|
||||
if (addColumn && addColumn?.onSearch) {
|
||||
|
||||
@@ -50,7 +50,7 @@ function Code({
|
||||
const match = /language-(\w+)/.exec(className || '');
|
||||
return !inline && match ? (
|
||||
<SyntaxHighlighter
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
style={a11yDark}
|
||||
language={match[1]}
|
||||
PreTag="div"
|
||||
@@ -115,7 +115,7 @@ function MarkdownRenderer({
|
||||
className={className}
|
||||
rehypePlugins={[rehypeRaw as any]}
|
||||
components={{
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
a: Link,
|
||||
pre: ({ children }) =>
|
||||
Pre({
|
||||
|
||||
@@ -196,17 +196,3 @@
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.members-table {
|
||||
.ant-table-tbody {
|
||||
> tr.members-table-row--tinted > td {
|
||||
background: rgba(0, 0, 0, 0.015);
|
||||
}
|
||||
|
||||
> tr:hover > td {
|
||||
background: rgba(0, 0, 0, 0.03) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,22 +167,3 @@
|
||||
padding-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.config-btn {
|
||||
&.missing-config-btn {
|
||||
background: var(--bg-amber-100);
|
||||
color: var(--bg-amber-500);
|
||||
|
||||
&:hover {
|
||||
color: var(--bg-amber-600) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.missing-config-btn {
|
||||
.config-btn-content {
|
||||
border-right: 1px solid var(--bg-amber-600);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 1. CUSTOM VALUES SUPPORT =====
|
||||
describe('Custom Values Support (CS)', () => {
|
||||
test('CS-01: Custom values persist in selected state', async () => {
|
||||
it('CS-01: Custom values persist in selected state', async () => {
|
||||
const { rerender } = renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={mockOptions}
|
||||
@@ -87,7 +87,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
expect(screen.getByText('another-custom')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('CS-02: Partial matches create custom values', async () => {
|
||||
it('CS-02: Partial matches create custom values', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={mockOptions}
|
||||
@@ -129,7 +129,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
expect(combobox).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('CS-03: Exact match filtering behavior', async () => {
|
||||
it('CS-03: Exact match filtering behavior', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -176,7 +176,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('CS-04: Search filtering with "end" pattern', async () => {
|
||||
it('CS-04: Search filtering with "end" pattern', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -234,7 +234,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('CS-05: Comma-separated values behavior', async () => {
|
||||
it('CS-05: Comma-separated values behavior', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -281,7 +281,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 2. SEARCH AND FILTERING =====
|
||||
describe('Search and Filtering (SF)', () => {
|
||||
test('SF-01: Selected values pushed to top', async () => {
|
||||
it('SF-01: Selected values pushed to top', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={mockOptions}
|
||||
@@ -305,7 +305,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('SF-02: Filtering with search text', async () => {
|
||||
it('SF-02: Filtering with search text', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -350,7 +350,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('SF-03: Highlighting search matches', async () => {
|
||||
it('SF-03: Highlighting search matches', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -381,7 +381,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('SF-04: Search with no results', async () => {
|
||||
it('SF-04: Search with no results', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -424,7 +424,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 3. KEYBOARD NAVIGATION =====
|
||||
describe('Keyboard Navigation (KN)', () => {
|
||||
test('KN-01: Arrow key navigation in dropdown', async () => {
|
||||
it('KN-01: Arrow key navigation in dropdown', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={mockOptions}
|
||||
@@ -465,7 +465,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('KN-02: Tab navigation to dropdown', async () => {
|
||||
it('KN-02: Tab navigation to dropdown', async () => {
|
||||
renderWithVirtuoso(
|
||||
<div>
|
||||
<input data-testid="prev-input" />
|
||||
@@ -515,7 +515,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('KN-03: Enter selection in dropdown', async () => {
|
||||
it('KN-03: Enter selection in dropdown', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={mockOptions}
|
||||
@@ -540,7 +540,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
expect(mockOnChange).toHaveBeenCalledWith(['frontend'], ['frontend']);
|
||||
});
|
||||
|
||||
test('KN-04: Chip deletion with keyboard', async () => {
|
||||
it('KN-04: Chip deletion with keyboard', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={mockOptions}
|
||||
@@ -586,7 +586,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 5. UI/UX BEHAVIORS =====
|
||||
describe('UI/UX Behaviors (UI)', () => {
|
||||
test('UI-01: Loading state does not block interaction', async () => {
|
||||
it('UI-01: Loading state does not block interaction', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} loading />,
|
||||
);
|
||||
@@ -603,7 +603,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('UI-02: Component remains editable in all states', async () => {
|
||||
it('UI-02: Component remains editable in all states', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} loading />,
|
||||
);
|
||||
@@ -634,7 +634,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
expect(combobox).not.toBeDisabled();
|
||||
});
|
||||
|
||||
test('UI-03: Toggle/Only labels in dropdown', async () => {
|
||||
it('UI-03: Toggle/Only labels in dropdown', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={mockOptions}
|
||||
@@ -656,7 +656,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('UI-04: Should display values with loading info at bottom', async () => {
|
||||
it('UI-04: Should display values with loading info at bottom', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} loading />,
|
||||
);
|
||||
@@ -677,7 +677,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('UI-05: Error state display in footer', async () => {
|
||||
it('UI-05: Error state display in footer', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={mockOptions}
|
||||
@@ -696,7 +696,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('UI-06: No data state display', async () => {
|
||||
it('UI-06: No data state display', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={[]}
|
||||
@@ -716,7 +716,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 6. CLEAR ACTIONS =====
|
||||
describe('Clear Actions (CA)', () => {
|
||||
test('CA-01: Ctrl+A selects all chips', async () => {
|
||||
it('CA-01: Ctrl+A selects all chips', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={mockOptions}
|
||||
@@ -760,7 +760,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('CA-02: Clear icon removes all selections', async () => {
|
||||
it('CA-02: Clear icon removes all selections', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={mockOptions}
|
||||
@@ -777,7 +777,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('CA-03: Individual chip removal', async () => {
|
||||
it('CA-03: Individual chip removal', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={mockOptions}
|
||||
@@ -790,7 +790,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
const removeButtons = document.querySelectorAll(
|
||||
'.ant-select-selection-item-remove',
|
||||
);
|
||||
expect(removeButtons.length).toBe(2);
|
||||
expect(removeButtons).toHaveLength(2);
|
||||
|
||||
await user.click(removeButtons[1] as Element);
|
||||
|
||||
@@ -804,7 +804,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 7. SAVE AND SELECTION TRIGGERS =====
|
||||
describe('Save and Selection Triggers (ST)', () => {
|
||||
test('ST-01: ESC triggers save action', async () => {
|
||||
it('ST-01: ESC triggers save action', async () => {
|
||||
const mockDropdownChange = jest.fn();
|
||||
|
||||
renderWithVirtuoso(
|
||||
@@ -837,7 +837,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('ST-02: Mouse selection works', async () => {
|
||||
it('ST-02: Mouse selection works', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -859,7 +859,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('ST-03: ENTER in input field creates custom value', async () => {
|
||||
it('ST-03: ENTER in input field creates custom value', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -892,7 +892,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('ST-04: Search text persistence', async () => {
|
||||
it('ST-04: Search text persistence', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -932,7 +932,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 8. SPECIAL OPTIONS AND STATES =====
|
||||
describe('Special Options and States (SO)', () => {
|
||||
test('SO-01: ALL option appears first and separated', async () => {
|
||||
it('SO-01: ALL option appears first and separated', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={mockOptions}
|
||||
@@ -954,7 +954,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('SO-02: ALL selection behavior', async () => {
|
||||
it('SO-02: ALL selection behavior', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={mockOptions}
|
||||
@@ -981,7 +981,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('SO-03: ALL tag display when all selected', () => {
|
||||
it('SO-03: ALL tag display when all selected', () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={mockOptions}
|
||||
@@ -996,7 +996,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
expect(screen.queryByText('frontend')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('SO-04: Footer information display', async () => {
|
||||
it('SO-04: Footer information display', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -1017,7 +1017,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== GROUPED OPTIONS SUPPORT =====
|
||||
describe('Grouped Options Support', () => {
|
||||
test('handles grouped options correctly', async () => {
|
||||
it('handles grouped options correctly', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockGroupedOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -1041,7 +1041,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== ACCESSIBILITY TESTS =====
|
||||
describe('Accessibility', () => {
|
||||
test('has proper ARIA attributes', async () => {
|
||||
it('has proper ARIA attributes', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -1058,7 +1058,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('supports screen reader navigation', async () => {
|
||||
it('supports screen reader navigation', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -1079,7 +1079,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 9. ADVANCED KEYBOARD NAVIGATION =====
|
||||
describe('Advanced Keyboard Navigation (AKN)', () => {
|
||||
test('AKN-01: Shift + Arrow + Del chip deletion', async () => {
|
||||
it('AKN-01: Shift + Arrow + Del chip deletion', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={mockOptions}
|
||||
@@ -1137,7 +1137,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
expect(combobox).toHaveFocus();
|
||||
});
|
||||
|
||||
test('AKN-03: Mouse out closes dropdown', async () => {
|
||||
it('AKN-03: Mouse out closes dropdown', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -1164,7 +1164,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 10. ADVANCED FILTERING AND HIGHLIGHTING =====
|
||||
describe('Advanced Filtering and Highlighting (AFH)', () => {
|
||||
test('AFH-01: Highlighted values pushed to top', async () => {
|
||||
it('AFH-01: Highlighted values pushed to top', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -1220,7 +1220,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('AFH-02: Distinction between selection Enter and save Enter', async () => {
|
||||
it('AFH-02: Distinction between selection Enter and save Enter', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -1267,7 +1267,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 11. ADVANCED CLEAR ACTIONS =====
|
||||
describe('Advanced Clear Actions (ACA)', () => {
|
||||
test('ACA-01: Clear action waiting behavior', async () => {
|
||||
it('ACA-01: Clear action waiting behavior', async () => {
|
||||
const mockOnChangeWithDelay = jest.fn().mockImplementation(
|
||||
() =>
|
||||
new Promise<void>((resolve) => {
|
||||
@@ -1300,7 +1300,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 12. ADVANCED UI STATES =====
|
||||
describe('Advanced UI States (AUS)', () => {
|
||||
test('AUS-01: No data with previous value selected', async () => {
|
||||
it('AUS-01: No data with previous value selected', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={[]}
|
||||
@@ -1322,7 +1322,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
expect(screen.getByText('previous-value')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('AUS-02: Always editable accessibility', async () => {
|
||||
it('AUS-02: Always editable accessibility', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} loading />,
|
||||
);
|
||||
@@ -1338,7 +1338,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
expect(combobox).not.toBeDisabled();
|
||||
});
|
||||
|
||||
test('AUS-03: Sufficient space for search value', async () => {
|
||||
it('AUS-03: Sufficient space for search value', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -1372,7 +1372,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 13. REGEX AND CUSTOM VALUES =====
|
||||
describe('Regex and Custom Values (RCV)', () => {
|
||||
test('RCV-01: Regex pattern support', async () => {
|
||||
it('RCV-01: Regex pattern support', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={mockOptions}
|
||||
@@ -1418,7 +1418,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('RCV-02: Custom values treated as normal dropdown values', async () => {
|
||||
it('RCV-02: Custom values treated as normal dropdown values', async () => {
|
||||
const customOptions = [
|
||||
...mockOptions,
|
||||
{ label: 'custom-value', value: 'custom-value', type: 'custom' as const },
|
||||
@@ -1456,7 +1456,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 14. DROPDOWN PERSISTENCE =====
|
||||
describe('Dropdown Persistence (DP)', () => {
|
||||
test('DP-01: Dropdown stays open for non-save actions', async () => {
|
||||
it('DP-01: Dropdown stays open for non-save actions', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
|
||||
@@ -50,7 +50,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 1. CUSTOM VALUES SUPPORT =====
|
||||
describe('Custom Values Support (CS)', () => {
|
||||
test('CS-02: Partial matches create custom values', async () => {
|
||||
it('CS-02: Partial matches create custom values', async () => {
|
||||
render(
|
||||
<CustomSelect
|
||||
options={mockOptions}
|
||||
@@ -110,7 +110,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('CS-03: Exact match behavior', async () => {
|
||||
it('CS-03: Exact match behavior', async () => {
|
||||
render(<CustomSelect options={mockOptions} onChange={mockOnChange} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
@@ -161,7 +161,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 2. SEARCH AND FILTERING =====
|
||||
describe('Search and Filtering (SF)', () => {
|
||||
test('SF-01: Selected values pushed to top', async () => {
|
||||
it('SF-01: Selected values pushed to top', async () => {
|
||||
render(
|
||||
<CustomSelect
|
||||
options={mockOptions}
|
||||
@@ -185,7 +185,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('SF-02: Real-time search filtering', async () => {
|
||||
it('SF-02: Real-time search filtering', async () => {
|
||||
render(<CustomSelect options={mockOptions} onChange={mockOnChange} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
@@ -228,7 +228,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('SF-03: Search highlighting', async () => {
|
||||
it('SF-03: Search highlighting', async () => {
|
||||
render(<CustomSelect options={mockOptions} onChange={mockOnChange} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
@@ -257,7 +257,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('SF-04: Search with partial matches', async () => {
|
||||
it('SF-04: Search with partial matches', async () => {
|
||||
render(<CustomSelect options={mockOptions} onChange={mockOnChange} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
@@ -298,7 +298,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 3. KEYBOARD NAVIGATION =====
|
||||
describe('Keyboard Navigation (KN)', () => {
|
||||
test('KN-01: Arrow key navigation in dropdown', async () => {
|
||||
it('KN-01: Arrow key navigation in dropdown', async () => {
|
||||
render(<CustomSelect options={mockOptions} onChange={mockOnChange} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
@@ -329,7 +329,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('KN-02: Tab navigation to dropdown', async () => {
|
||||
it('KN-02: Tab navigation to dropdown', async () => {
|
||||
render(
|
||||
<div>
|
||||
<input data-testid="prev-input" />
|
||||
@@ -355,7 +355,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('KN-03: Enter selection in dropdown', async () => {
|
||||
it('KN-03: Enter selection in dropdown', async () => {
|
||||
render(<CustomSelect options={mockOptions} onChange={mockOnChange} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
@@ -376,7 +376,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('KN-04: Space key selection', async () => {
|
||||
it('KN-04: Space key selection', async () => {
|
||||
render(<CustomSelect options={mockOptions} onChange={mockOnChange} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
@@ -396,7 +396,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('KN-05: Tab navigation within dropdown', async () => {
|
||||
it('KN-05: Tab navigation within dropdown', async () => {
|
||||
render(<CustomSelect options={mockOptions} onChange={mockOnChange} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
@@ -417,7 +417,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 4. UI/UX BEHAVIORS =====
|
||||
describe('UI/UX Behaviors (UI)', () => {
|
||||
test('UI-01: Loading state does not block interaction', async () => {
|
||||
it('UI-01: Loading state does not block interaction', async () => {
|
||||
render(
|
||||
<CustomSelect options={mockOptions} onChange={mockOnChange} loading />,
|
||||
);
|
||||
@@ -429,7 +429,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
expect(combobox).toHaveFocus();
|
||||
});
|
||||
|
||||
test('UI-02: Component remains editable in all states', () => {
|
||||
it('UI-02: Component remains editable in all states', () => {
|
||||
render(
|
||||
<CustomSelect
|
||||
options={mockOptions}
|
||||
@@ -444,7 +444,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
expect(combobox).not.toBeDisabled();
|
||||
});
|
||||
|
||||
test('UI-03: Loading state display in footer', async () => {
|
||||
it('UI-03: Loading state display in footer', async () => {
|
||||
render(
|
||||
<CustomSelect options={mockOptions} onChange={mockOnChange} loading />,
|
||||
);
|
||||
@@ -458,7 +458,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('UI-04: Error state display in footer', async () => {
|
||||
it('UI-04: Error state display in footer', async () => {
|
||||
render(
|
||||
<CustomSelect
|
||||
options={mockOptions}
|
||||
@@ -477,7 +477,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('UI-05: No data state display', async () => {
|
||||
it('UI-05: No data state display', async () => {
|
||||
render(
|
||||
<CustomSelect
|
||||
options={[]}
|
||||
@@ -497,7 +497,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 6. SAVE AND SELECTION TRIGGERS =====
|
||||
describe('Save and Selection Triggers (ST)', () => {
|
||||
test('ST-01: Mouse selection works', async () => {
|
||||
it('ST-01: Mouse selection works', async () => {
|
||||
render(<CustomSelect options={mockOptions} onChange={mockOnChange} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
@@ -520,7 +520,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 7. GROUPED OPTIONS SUPPORT =====
|
||||
describe('Grouped Options Support', () => {
|
||||
test('handles grouped options correctly', async () => {
|
||||
it('handles grouped options correctly', async () => {
|
||||
render(
|
||||
<CustomSelect options={mockGroupedOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -541,7 +541,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('grouped option selection works', async () => {
|
||||
it('grouped option selection works', async () => {
|
||||
render(
|
||||
<CustomSelect options={mockGroupedOptions} onChange={mockOnChange} />,
|
||||
);
|
||||
@@ -566,7 +566,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 8. ACCESSIBILITY =====
|
||||
describe('Accessibility', () => {
|
||||
test('has proper ARIA attributes', async () => {
|
||||
it('has proper ARIA attributes', async () => {
|
||||
render(<CustomSelect options={mockOptions} onChange={mockOnChange} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
@@ -580,7 +580,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('supports screen reader navigation', async () => {
|
||||
it('supports screen reader navigation', async () => {
|
||||
render(<CustomSelect options={mockOptions} onChange={mockOnChange} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
@@ -596,7 +596,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('has proper focus management', async () => {
|
||||
it('has proper focus management', async () => {
|
||||
render(<CustomSelect options={mockOptions} onChange={mockOnChange} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
@@ -617,7 +617,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 10. EDGE CASES =====
|
||||
describe('Edge Cases', () => {
|
||||
test('handles special characters in options', async () => {
|
||||
it('handles special characters in options', async () => {
|
||||
const specialOptions = [
|
||||
{ label: 'Option with spaces', value: 'option-with-spaces' },
|
||||
{ label: 'Option-with-dashes', value: 'option-with-dashes' },
|
||||
@@ -638,7 +638,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('handles extremely long option labels', async () => {
|
||||
it('handles extremely long option labels', async () => {
|
||||
const longLabelOptions = [
|
||||
{
|
||||
label:
|
||||
@@ -663,7 +663,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 11. ADVANCED KEYBOARD NAVIGATION =====
|
||||
describe('Advanced Keyboard Navigation (AKN)', () => {
|
||||
test('AKN-01: Mouse out closes dropdown', async () => {
|
||||
it('AKN-01: Mouse out closes dropdown', async () => {
|
||||
render(<CustomSelect options={mockOptions} onChange={mockOnChange} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
@@ -684,7 +684,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('AKN-02: TAB navigation from input to dropdown', async () => {
|
||||
it('AKN-02: TAB navigation from input to dropdown', async () => {
|
||||
render(
|
||||
<div>
|
||||
<input data-testid="prev-input" />
|
||||
@@ -722,7 +722,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 12. ADVANCED FILTERING AND HIGHLIGHTING =====
|
||||
describe('Advanced Filtering and Highlighting (AFH)', () => {
|
||||
test('AFH-01: Highlighted values pushed to top', async () => {
|
||||
it('AFH-01: Highlighted values pushed to top', async () => {
|
||||
render(<CustomSelect options={mockOptions} onChange={mockOnChange} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
@@ -776,7 +776,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('AFH-02: Distinction between selection Enter and save Enter', async () => {
|
||||
it('AFH-02: Distinction between selection Enter and save Enter', async () => {
|
||||
render(<CustomSelect options={mockOptions} onChange={mockOnChange} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
@@ -830,7 +830,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 13. ADVANCED CLEAR ACTIONS =====
|
||||
describe('Advanced Clear Actions (ACA)', () => {
|
||||
test('ACA-01: Clear action waiting behavior', async () => {
|
||||
it('ACA-01: Clear action waiting behavior', async () => {
|
||||
const mockOnChangeWithDelay = jest.fn().mockImplementation(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
@@ -860,7 +860,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
expect(mockOnChangeWithDelay).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('ACA-02: Single select clear behavior like text input', async () => {
|
||||
it('ACA-02: Single select clear behavior like text input', async () => {
|
||||
render(
|
||||
<CustomSelect
|
||||
options={mockOptions}
|
||||
@@ -883,7 +883,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 14. ADVANCED UI STATES =====
|
||||
describe('Advanced UI States (AUS)', () => {
|
||||
test('AUS-01: No data with previous value selected', async () => {
|
||||
it('AUS-01: No data with previous value selected', async () => {
|
||||
render(
|
||||
<CustomSelect
|
||||
options={[]}
|
||||
@@ -905,7 +905,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
expect(screen.getAllByText('previous-value')).toHaveLength(2);
|
||||
});
|
||||
|
||||
test('AUS-02: Always editable accessibility', async () => {
|
||||
it('AUS-02: Always editable accessibility', async () => {
|
||||
render(
|
||||
<CustomSelect options={mockOptions} onChange={mockOnChange} loading />,
|
||||
);
|
||||
@@ -921,7 +921,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
expect(combobox).not.toBeDisabled();
|
||||
});
|
||||
|
||||
test('AUS-03: Sufficient space for search value', async () => {
|
||||
it('AUS-03: Sufficient space for search value', async () => {
|
||||
render(<CustomSelect options={mockOptions} onChange={mockOnChange} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
@@ -950,7 +950,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('AUS-04: No spinners blocking user interaction', async () => {
|
||||
it('AUS-04: No spinners blocking user interaction', async () => {
|
||||
render(
|
||||
<CustomSelect options={mockOptions} onChange={mockOnChange} loading />,
|
||||
);
|
||||
@@ -976,7 +976,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 15. REGEX AND CUSTOM VALUES =====
|
||||
describe('Regex and Custom Values (RCV)', () => {
|
||||
test('RCV-01: Regex pattern support', async () => {
|
||||
it('RCV-01: Regex pattern support', async () => {
|
||||
render(<CustomSelect options={mockOptions} onChange={mockOnChange} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
@@ -1019,7 +1019,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('RCV-02: Custom values treated as normal dropdown values', async () => {
|
||||
it('RCV-02: Custom values treated as normal dropdown values', async () => {
|
||||
const customOptions = [
|
||||
...mockOptions,
|
||||
{ label: 'custom-value', value: 'custom-value', type: 'custom' as const },
|
||||
@@ -1051,7 +1051,7 @@ describe('CustomSelect - Comprehensive Tests', () => {
|
||||
|
||||
// ===== 16. DROPDOWN PERSISTENCE =====
|
||||
describe('Dropdown Persistence (DP)', () => {
|
||||
test('DP-01: Dropdown closes only on save actions', async () => {
|
||||
it('DP-01: Dropdown closes only on save actions', async () => {
|
||||
render(<CustomSelect options={mockOptions} onChange={mockOnChange} />);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
|
||||
@@ -86,7 +86,7 @@ describe('VariableItem Integration Tests', () => {
|
||||
|
||||
// ===== 1. INTEGRATION WITH CUSTOMSELECT =====
|
||||
describe('CustomSelect Integration (VI)', () => {
|
||||
test('VI-01: Single select variable integration', async () => {
|
||||
it('VI-01: Single select variable integration', async () => {
|
||||
const variable = createMockVariable({
|
||||
multiSelect: false,
|
||||
type: 'CUSTOM',
|
||||
@@ -130,7 +130,7 @@ describe('VariableItem Integration Tests', () => {
|
||||
|
||||
// ===== 2. INTEGRATION WITH CUSTOMMULTISELECT =====
|
||||
describe('CustomMultiSelect Integration (VI)', () => {
|
||||
test('VI-02: Multi select variable integration', async () => {
|
||||
it('VI-02: Multi select variable integration', async () => {
|
||||
const variable = createMockVariable({
|
||||
multiSelect: true,
|
||||
type: 'CUSTOM',
|
||||
@@ -174,7 +174,7 @@ describe('VariableItem Integration Tests', () => {
|
||||
|
||||
// ===== 3. TEXTBOX VARIABLE TYPE =====
|
||||
describe('Textbox Variable Integration', () => {
|
||||
test('VI-03: Textbox variable handling', async () => {
|
||||
it('VI-03: Textbox variable handling', async () => {
|
||||
const variable = createMockVariable({
|
||||
type: 'TEXTBOX',
|
||||
selectedValue: 'initial-value',
|
||||
@@ -219,7 +219,7 @@ describe('VariableItem Integration Tests', () => {
|
||||
|
||||
// ===== 4. VALUE PERSISTENCE AND STATE MANAGEMENT =====
|
||||
describe('Value Persistence and State Management', () => {
|
||||
test('VI-04: All selected state handling', () => {
|
||||
it('VI-04: All selected state handling', () => {
|
||||
const variable = createMockVariable({
|
||||
multiSelect: true,
|
||||
type: 'CUSTOM',
|
||||
@@ -243,7 +243,7 @@ describe('VariableItem Integration Tests', () => {
|
||||
expect(screen.getByText('ALL')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('VI-05: Dropdown behavior with temporary selections', async () => {
|
||||
it('VI-05: Dropdown behavior with temporary selections', async () => {
|
||||
const variable = createMockVariable({
|
||||
multiSelect: true,
|
||||
type: 'CUSTOM',
|
||||
@@ -277,7 +277,7 @@ describe('VariableItem Integration Tests', () => {
|
||||
|
||||
// ===== 6. ACCESSIBILITY AND USER EXPERIENCE =====
|
||||
describe('Accessibility and User Experience', () => {
|
||||
test('VI-06: Variable description tooltip', async () => {
|
||||
it('VI-06: Variable description tooltip', async () => {
|
||||
const variable = createMockVariable({
|
||||
description: 'This variable controls the service selection',
|
||||
type: 'CUSTOM',
|
||||
@@ -310,7 +310,7 @@ describe('VariableItem Integration Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('VI-07: Variable name display', () => {
|
||||
it('VI-07: Variable name display', () => {
|
||||
const variable = createMockVariable({
|
||||
name: 'service_name',
|
||||
type: 'CUSTOM',
|
||||
@@ -331,7 +331,7 @@ describe('VariableItem Integration Tests', () => {
|
||||
expect(screen.getByText('$service_name')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('VI-08: Max tag count behavior', async () => {
|
||||
it('VI-08: Max tag count behavior', async () => {
|
||||
const variable = createMockVariable({
|
||||
multiSelect: true,
|
||||
type: 'CUSTOM',
|
||||
@@ -365,7 +365,7 @@ describe('VariableItem Integration Tests', () => {
|
||||
|
||||
// ===== 8. SEARCH INTERACTION TESTS =====
|
||||
describe('Search Interaction Tests', () => {
|
||||
test('VI-14: Search persistence across dropdown open/close', async () => {
|
||||
it('VI-14: Search persistence across dropdown open/close', async () => {
|
||||
const variable = createMockVariable({
|
||||
type: 'CUSTOM',
|
||||
customValue: 'option1,option2,option3',
|
||||
@@ -417,7 +417,7 @@ describe('VariableItem Integration Tests', () => {
|
||||
|
||||
// ===== 9. ADVANCED KEYBOARD NAVIGATION =====
|
||||
describe('Advanced Keyboard Navigation (VI)', () => {
|
||||
test('VI-15: Shift + Arrow + Del chip deletion in multiselect', async () => {
|
||||
it('VI-15: Shift + Arrow + Del chip deletion in multiselect', async () => {
|
||||
const variable = createMockVariable({
|
||||
type: 'CUSTOM',
|
||||
customValue: 'option1,option2,option3',
|
||||
@@ -461,7 +461,7 @@ describe('VariableItem Integration Tests', () => {
|
||||
|
||||
// ===== 11. ADVANCED UI STATES =====
|
||||
describe('Advanced UI States (VI)', () => {
|
||||
test('VI-19: No data with previous value selected in variable', async () => {
|
||||
it('VI-19: No data with previous value selected in variable', async () => {
|
||||
const variable = createMockVariable({
|
||||
type: 'CUSTOM',
|
||||
customValue: '',
|
||||
@@ -499,7 +499,7 @@ describe('VariableItem Integration Tests', () => {
|
||||
expect(combobox).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('VI-20: Always editable accessibility in variable', async () => {
|
||||
it('VI-20: Always editable accessibility in variable', async () => {
|
||||
const variable = createMockVariable({
|
||||
type: 'CUSTOM',
|
||||
customValue: 'option1,option2',
|
||||
@@ -530,7 +530,7 @@ describe('VariableItem Integration Tests', () => {
|
||||
|
||||
// ===== 13. DROPDOWN PERSISTENCE =====
|
||||
describe('Dropdown Persistence (VI)', () => {
|
||||
test('VI-24: Dropdown stays open for non-save actions in variable', async () => {
|
||||
it('VI-24: Dropdown stays open for non-save actions in variable', async () => {
|
||||
const variable = createMockVariable({
|
||||
type: 'CUSTOM',
|
||||
customValue: 'option1,option2,option3',
|
||||
|
||||
@@ -16,7 +16,7 @@ $custom-border-color: #2c3044;
|
||||
}
|
||||
|
||||
.ant-select-selection-placeholder {
|
||||
color: color-mix(in srgb, var(--border) 45%, transparent);
|
||||
color: color-mix(in srgb, var(--l2-foreground) 45%, transparent);
|
||||
}
|
||||
|
||||
// Base styles are for dark mode
|
||||
@@ -48,10 +48,6 @@ $custom-border-color: #2c3044;
|
||||
visibility: visible !important;
|
||||
pointer-events: none;
|
||||
z-index: 2;
|
||||
|
||||
.lightMode & {
|
||||
color: rgba(0, 0, 0, 0.85) !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.ant-select-focused .ant-select-selection-placeholder {
|
||||
@@ -67,10 +63,6 @@ $custom-border-color: #2c3044;
|
||||
color: var(--l2-foreground);
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
|
||||
.lightMode & {
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
}
|
||||
}
|
||||
|
||||
.ant-select-selector {
|
||||
@@ -114,7 +106,7 @@ $custom-border-color: #2c3044;
|
||||
}
|
||||
|
||||
.ant-select-selection-placeholder {
|
||||
color: color-mix(in srgb, var(--border) 45%, transparent);
|
||||
color: color-mix(in srgb, var(--l2-foreground) 45%, transparent);
|
||||
}
|
||||
|
||||
// Customize tags in multiselect (dark mode by default)
|
||||
@@ -217,7 +209,7 @@ $custom-border-color: #2c3044;
|
||||
.empty-message {
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
color: color-mix(in srgb, var(--border) 45%, transparent);
|
||||
color: color-mix(in srgb, var(--l1-foreground) 45%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,7 +567,7 @@ $custom-border-color: #2c3044;
|
||||
.empty-message {
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
color: color-mix(in srgb, var(--border) 45%, transparent);
|
||||
color: color-mix(in srgb, var(--l1-foreground) 45%, transparent);
|
||||
}
|
||||
|
||||
.status-message {
|
||||
@@ -983,10 +975,6 @@ $custom-border-color: #2c3044;
|
||||
transition:
|
||||
opacity 0.2s ease,
|
||||
visibility 0.2s ease;
|
||||
|
||||
.lightMode & {
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
}
|
||||
}
|
||||
|
||||
&:focus-within .all-text {
|
||||
|
||||
@@ -44,7 +44,7 @@ describe('OverflowInputToolTip', () => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
test('shows tooltip when content overflows and input is clamped at maxAutoWidth', async () => {
|
||||
it('shows tooltip when content overflows and input is clamped at maxAutoWidth', async () => {
|
||||
mockOverflow(150, 250); // clientWidth >= maxAutoWidth (150), scrollWidth > clientWidth
|
||||
|
||||
render(<OverflowInputToolTip value="Very long overflowing text" />);
|
||||
@@ -64,7 +64,7 @@ describe('OverflowInputToolTip', () => {
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('does NOT show tooltip when content does not overflow', async () => {
|
||||
it('does NOT show tooltip when content does not overflow', async () => {
|
||||
mockOverflow(150, 100); // content fits (scrollWidth <= clientWidth)
|
||||
|
||||
render(<OverflowInputToolTip value="Short text" />);
|
||||
@@ -76,7 +76,7 @@ describe('OverflowInputToolTip', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('does NOT show tooltip when content overflows but input is NOT at maxAutoWidth', async () => {
|
||||
it('does NOT show tooltip when content overflows but input is NOT at maxAutoWidth', async () => {
|
||||
mockOverflow(100, 250); // clientWidth < maxAutoWidth (150), scrollWidth > clientWidth
|
||||
|
||||
render(<OverflowInputToolTip value="Long but input not clamped" />);
|
||||
@@ -88,7 +88,7 @@ describe('OverflowInputToolTip', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('uncontrolled input allows typing', async () => {
|
||||
it('uncontrolled input allows typing', async () => {
|
||||
render(<OverflowInputToolTip defaultValue="Init" />);
|
||||
|
||||
const input = screen.getByRole('textbox') as HTMLInputElement;
|
||||
@@ -97,7 +97,7 @@ describe('OverflowInputToolTip', () => {
|
||||
expect(input).toHaveValue('InitABC');
|
||||
});
|
||||
|
||||
test('disabled input never shows tooltip even if overflowing', async () => {
|
||||
it('disabled input never shows tooltip even if overflowing', async () => {
|
||||
mockOverflow(150, 300);
|
||||
|
||||
render(<OverflowInputToolTip value="Overflowing!" disabled />);
|
||||
@@ -109,7 +109,7 @@ describe('OverflowInputToolTip', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('renders mirror span and input correctly (structural assertions instead of snapshot)', () => {
|
||||
it('renders mirror span and input correctly (structural assertions instead of snapshot)', () => {
|
||||
const { container } = render(<OverflowInputToolTip value="Snapshot" />);
|
||||
const mirror = container.querySelector('.overflow-input-mirror');
|
||||
const input = container.querySelector('input') as HTMLInputElement | null;
|
||||
|
||||
@@ -249,57 +249,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.query-aggregation-container {
|
||||
.aggregation-container {
|
||||
.query-aggregation-select-container {
|
||||
.query-aggregation-select-editor {
|
||||
.cm-editor {
|
||||
.cm-tooltip-autocomplete {
|
||||
background: var(--l1-background) !important;
|
||||
border: 1px solid var(--l1-border) !important;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1) !important;
|
||||
backdrop-filter: none;
|
||||
|
||||
ul {
|
||||
li {
|
||||
&:hover,
|
||||
&[aria-selected='true'] {
|
||||
background: var(--l3-background) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cm-line {
|
||||
::-moz-selection {
|
||||
background: var(--l2-background) !important;
|
||||
opacity: 0.5 !important;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: var(--l1-background) !important;
|
||||
opacity: 0.5 !important;
|
||||
}
|
||||
|
||||
.cm-function {
|
||||
color: var(--primary-background) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.query-aggregation-error-popover {
|
||||
.ant-popover-inner {
|
||||
background-color: var(--l1-background);
|
||||
border: none;
|
||||
box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.query-aggregation-error-popover {
|
||||
.ant-popover-inner {
|
||||
background-color: var(--l1-border);
|
||||
|
||||
@@ -121,44 +121,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.qb-trace-operator {
|
||||
&-arrow {
|
||||
&::before {
|
||||
background: repeating-linear-gradient(
|
||||
to right,
|
||||
var(--l3-background),
|
||||
var(--l3-background) 4px,
|
||||
transparent 4px,
|
||||
transparent 8px
|
||||
);
|
||||
}
|
||||
&::after {
|
||||
background-color: var(--l3-background);
|
||||
}
|
||||
}
|
||||
&.non-list-view {
|
||||
&::before {
|
||||
background: repeating-linear-gradient(
|
||||
to bottom,
|
||||
var(--l3-background),
|
||||
var(--l3-background) 4px,
|
||||
transparent 4px,
|
||||
transparent 8px
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
&-label-with-input {
|
||||
border: 1px solid var(--l1-border) !important;
|
||||
background: var(--l1-background) !important;
|
||||
|
||||
.label {
|
||||
color: var(--l1-foreground) !important;
|
||||
border-right: 1px solid var(--l1-border) !important;
|
||||
background: var(--l1-background) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ describe('traceOperatorContextUtils', () => {
|
||||
null,
|
||||
);
|
||||
|
||||
expect(context).toEqual({
|
||||
expect(context).toStrictEqual({
|
||||
tokenType: TraceOperatorGrammarLexer.IDENTIFIER,
|
||||
text: 'test',
|
||||
start: 0,
|
||||
@@ -62,7 +62,7 @@ describe('traceOperatorContextUtils', () => {
|
||||
false,
|
||||
);
|
||||
|
||||
expect(context).toEqual({
|
||||
expect(context).toStrictEqual({
|
||||
tokenType: TraceOperatorGrammarLexer.IDENTIFIER,
|
||||
text: 'test',
|
||||
start: 0,
|
||||
@@ -193,7 +193,7 @@ describe('traceOperatorContextUtils', () => {
|
||||
it('should return default context for empty query', () => {
|
||||
const result = getTraceOperatorContextAtCursor('', 0);
|
||||
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
tokenType: -1,
|
||||
text: '',
|
||||
start: 0,
|
||||
@@ -211,7 +211,7 @@ describe('traceOperatorContextUtils', () => {
|
||||
it('should return default context for null query', () => {
|
||||
const result = getTraceOperatorContextAtCursor(null as any, 0);
|
||||
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
tokenType: -1,
|
||||
text: '',
|
||||
start: 0,
|
||||
@@ -229,7 +229,7 @@ describe('traceOperatorContextUtils', () => {
|
||||
it('should return default context for undefined query', () => {
|
||||
const result = getTraceOperatorContextAtCursor(undefined as any, 0);
|
||||
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
tokenType: -1,
|
||||
text: '',
|
||||
start: 0,
|
||||
|
||||
@@ -8,21 +8,21 @@ const makeTraceOperator = (expression: string): IBuilderTraceOperator =>
|
||||
describe('getInvolvedQueriesInTraceOperator', () => {
|
||||
it('returns empty array for empty input', () => {
|
||||
const result = getInvolvedQueriesInTraceOperator([]);
|
||||
expect(result).toEqual([]);
|
||||
expect(result).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('extracts identifiers from expression', () => {
|
||||
const result = getInvolvedQueriesInTraceOperator([
|
||||
makeTraceOperator('A => B'),
|
||||
]);
|
||||
expect(result).toEqual(['A', 'B']);
|
||||
expect(result).toStrictEqual(['A', 'B']);
|
||||
});
|
||||
|
||||
it('extracts identifiers from complex expression', () => {
|
||||
const result = getInvolvedQueriesInTraceOperator([
|
||||
makeTraceOperator('A => (NOT B || C)'),
|
||||
]);
|
||||
expect(result).toEqual(['A', 'B', 'C']);
|
||||
expect(result).toStrictEqual(['A', 'B', 'C']);
|
||||
});
|
||||
|
||||
it('filters out querynames from complex expression', () => {
|
||||
@@ -31,7 +31,7 @@ describe('getInvolvedQueriesInTraceOperator', () => {
|
||||
'(A1 && (NOT B2 || (C3 -> (D4 && E5)))) => ((F6 || G7) && (NOT (H8 -> I9)))',
|
||||
),
|
||||
]);
|
||||
expect(result).toEqual([
|
||||
expect(result).toStrictEqual([
|
||||
'A1',
|
||||
'B2',
|
||||
'C3',
|
||||
|
||||
@@ -85,7 +85,7 @@ describe('previousQuery.utils', () => {
|
||||
saveAsPreviousQuery(key, sampleQuery);
|
||||
|
||||
const fromStore = getPreviousQueryFromKey(key);
|
||||
expect(fromStore).toEqual(sampleQuery);
|
||||
expect(fromStore).toStrictEqual(sampleQuery);
|
||||
});
|
||||
|
||||
it('saveAsPreviousQuery merges multiple entries and removeKeyFromPreviousQuery deletes one', () => {
|
||||
|
||||
@@ -22,18 +22,20 @@ describe('convertFiltersToExpression', () => {
|
||||
|
||||
it('should handle empty, null, and undefined inputs', () => {
|
||||
// Test null and undefined
|
||||
expect(convertFiltersToExpression(null as any)).toEqual({ expression: '' });
|
||||
expect(convertFiltersToExpression(undefined as any)).toEqual({
|
||||
expect(convertFiltersToExpression(null as any)).toStrictEqual({
|
||||
expression: '',
|
||||
});
|
||||
expect(convertFiltersToExpression(undefined as any)).toStrictEqual({
|
||||
expression: '',
|
||||
});
|
||||
|
||||
// Test empty filters
|
||||
expect(convertFiltersToExpression({ items: [], op: 'AND' })).toEqual({
|
||||
expect(convertFiltersToExpression({ items: [], op: 'AND' })).toStrictEqual({
|
||||
expression: '',
|
||||
});
|
||||
expect(
|
||||
convertFiltersToExpression({ items: undefined, op: 'AND' } as any),
|
||||
).toEqual({ expression: '' });
|
||||
).toStrictEqual({ expression: '' });
|
||||
});
|
||||
|
||||
it('should convert basic comparison operators with proper value formatting', () => {
|
||||
@@ -92,7 +94,7 @@ describe('convertFiltersToExpression', () => {
|
||||
};
|
||||
|
||||
const result = convertFiltersToExpression(filters);
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
expression:
|
||||
"service = 'api-gateway' AND status != 'error' AND duration > 100 AND count <= 50 AND is_active = true AND enabled = false AND count = 0 AND regex REGEXP '.*'",
|
||||
});
|
||||
@@ -124,7 +126,7 @@ describe('convertFiltersToExpression', () => {
|
||||
};
|
||||
|
||||
const result = convertFiltersToExpression(filters);
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
expression:
|
||||
"message = 'user\\'s data' AND description = '' AND path = '/api/v1/users'",
|
||||
});
|
||||
@@ -162,7 +164,7 @@ describe('convertFiltersToExpression', () => {
|
||||
};
|
||||
|
||||
const result = convertFiltersToExpression(filters);
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
expression:
|
||||
"service in ['api-gateway', 'user-service', 'auth-service'] AND status in ['success'] AND tags in [] AND name in ['John\\'s', 'Mary\\'s', 'Bob']",
|
||||
});
|
||||
@@ -224,7 +226,7 @@ describe('convertFiltersToExpression', () => {
|
||||
};
|
||||
|
||||
const result = convertFiltersToExpression(filters);
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
expression:
|
||||
"service NOT IN ['api-gateway', 'user-service'] AND message NOT LIKE 'error' AND path NOT REGEXP '/api/.*' AND service NOT IN ['api-gateway'] AND user_id NOT EXISTS AND description NOT CONTAINS 'error' AND NOT has(tags, 'production') AND NOT hasAny(labels, ['env:prod', 'service:api'])",
|
||||
});
|
||||
@@ -268,7 +270,7 @@ describe('convertFiltersToExpression', () => {
|
||||
};
|
||||
|
||||
const result = convertFiltersToExpression(filters);
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
expression:
|
||||
"user_id exists AND user_id exists AND has(tags, 'production') AND hasAny(tags, ['production', 'staging']) AND hasAll(tags, ['production', 'monitoring'])",
|
||||
});
|
||||
@@ -312,7 +314,7 @@ describe('convertFiltersToExpression', () => {
|
||||
};
|
||||
|
||||
const result = convertFiltersToExpression(filters);
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
expression:
|
||||
"service = 'api-gateway' AND status = 'success' AND service in ['api-gateway']",
|
||||
});
|
||||
@@ -362,7 +364,7 @@ describe('convertFiltersToExpression', () => {
|
||||
};
|
||||
|
||||
const result = convertFiltersToExpression(filters);
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
expression:
|
||||
"service in ['api-gateway', 'user-service'] AND user_id exists AND has(tags, 'production') AND duration > 100 AND status NOT IN ['error', 'timeout'] AND method = 'POST'",
|
||||
});
|
||||
@@ -412,7 +414,7 @@ describe('convertFiltersToExpression', () => {
|
||||
};
|
||||
|
||||
const result = convertFiltersToExpression(filters);
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
expression:
|
||||
"count = 0 AND score > 100 AND limit >= 50 AND threshold < 1000 AND max_value <= 999 AND values in ['1', '2', '3', '4', '5']",
|
||||
});
|
||||
@@ -456,7 +458,7 @@ describe('convertFiltersToExpression', () => {
|
||||
};
|
||||
|
||||
const result = convertFiltersToExpression(filters);
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
expression:
|
||||
"is_active = true AND is_deleted = false AND email = 'user@example.com' AND description = 'Contains \"quotes\" and \\'apostrophes\\'' AND path = '/api/v1/users/123?filter=true'",
|
||||
});
|
||||
@@ -506,7 +508,7 @@ describe('convertFiltersToExpression', () => {
|
||||
};
|
||||
|
||||
const result = convertFiltersToExpression(filters);
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
expression:
|
||||
"has(tags, 'production') AND hasAny(labels, ['env:prod', 'service:api']) AND hasAll(metadata, ['version:1.0', 'team:backend']) AND services in ['api-gateway', 'user-service', 'auth-service', 'payment-service'] AND excluded_services NOT IN ['legacy-service', 'deprecated-service'] AND status_codes in ['200', '201', '400', '500']",
|
||||
});
|
||||
@@ -544,7 +546,7 @@ describe('convertFiltersToExpression', () => {
|
||||
};
|
||||
|
||||
const result = convertFiltersToExpression(filters);
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
expression:
|
||||
"user_id NOT EXISTS AND description NOT CONTAINS 'error' AND NOT has(tags, 'production') AND NOT hasAny(labels, ['env:prod', 'service:api'])",
|
||||
});
|
||||
@@ -568,7 +570,7 @@ describe('convertFiltersToExpression', () => {
|
||||
undefined,
|
||||
);
|
||||
|
||||
expect(result.filters).toEqual(filters);
|
||||
expect(result.filters).toStrictEqual(filters);
|
||||
expect(result.filter.expression).toBe("service.name = 'test-service'");
|
||||
});
|
||||
|
||||
@@ -583,7 +585,7 @@ describe('convertFiltersToExpression', () => {
|
||||
undefined,
|
||||
);
|
||||
|
||||
expect(result.filters).toEqual(filters);
|
||||
expect(result.filters).toStrictEqual(filters);
|
||||
expect(result.filter.expression).toBe('');
|
||||
});
|
||||
|
||||
@@ -611,7 +613,7 @@ describe('convertFiltersToExpression', () => {
|
||||
expect(result.filter).toBeDefined();
|
||||
expect(result.filter.expression).toBe("service.name = 'updated-service'");
|
||||
// Ensure parser can parse the existing query
|
||||
expect(extractQueryPairs(existingQuery)).toEqual(
|
||||
expect(extractQueryPairs(existingQuery)).toStrictEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
key: 'service.name',
|
||||
@@ -805,7 +807,7 @@ describe('convertAggregationToExpression', () => {
|
||||
temporality: 'delta',
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
expect(result).toStrictEqual([
|
||||
{
|
||||
metricName: 'test_metric',
|
||||
timeAggregation: 'avg',
|
||||
@@ -825,9 +827,11 @@ describe('convertAggregationToExpression', () => {
|
||||
spaceAggregation: 'noop',
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
expect(result).toStrictEqual([
|
||||
{
|
||||
metricName: 'test_metric',
|
||||
reduceTo: undefined,
|
||||
temporality: undefined,
|
||||
timeAggregation: 'count',
|
||||
spaceAggregation: 'count',
|
||||
},
|
||||
@@ -841,9 +845,11 @@ describe('convertAggregationToExpression', () => {
|
||||
dataSource: DataSource.METRICS,
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
expect(result).toStrictEqual([
|
||||
{
|
||||
metricName: '',
|
||||
reduceTo: undefined,
|
||||
temporality: undefined,
|
||||
timeAggregation: 'sum',
|
||||
spaceAggregation: 'sum',
|
||||
},
|
||||
@@ -858,7 +864,7 @@ describe('convertAggregationToExpression', () => {
|
||||
alias: 'trace_alias',
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
expect(result).toStrictEqual([
|
||||
{
|
||||
expression: 'count(test_metric)',
|
||||
alias: 'trace_alias',
|
||||
@@ -874,7 +880,7 @@ describe('convertAggregationToExpression', () => {
|
||||
alias: 'log_alias',
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
expect(result).toStrictEqual([
|
||||
{
|
||||
expression: 'avg(test_metric)',
|
||||
alias: 'log_alias',
|
||||
@@ -889,7 +895,7 @@ describe('convertAggregationToExpression', () => {
|
||||
dataSource: DataSource.TRACES,
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
expect(result).toStrictEqual([
|
||||
{
|
||||
expression: 'count()',
|
||||
},
|
||||
@@ -903,7 +909,7 @@ describe('convertAggregationToExpression', () => {
|
||||
dataSource: DataSource.LOGS,
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
expect(result).toStrictEqual([
|
||||
{
|
||||
expression: 'sum(test_metric)',
|
||||
},
|
||||
@@ -917,9 +923,11 @@ describe('convertAggregationToExpression', () => {
|
||||
dataSource: DataSource.METRICS,
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
expect(result).toStrictEqual([
|
||||
{
|
||||
metricName: 'test_metric',
|
||||
reduceTo: undefined,
|
||||
temporality: undefined,
|
||||
timeAggregation: 'max',
|
||||
spaceAggregation: 'max',
|
||||
},
|
||||
@@ -933,7 +941,7 @@ describe('convertAggregationToExpression', () => {
|
||||
dataSource: DataSource.METRICS,
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
expect(result).toStrictEqual([
|
||||
{
|
||||
metricName: 'test_metric',
|
||||
timeAggregation: 'sum',
|
||||
@@ -951,7 +959,7 @@ describe('convertAggregationToExpression', () => {
|
||||
dataSource: DataSource.TRACES,
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
expect(result).toStrictEqual([
|
||||
{
|
||||
expression: 'count()',
|
||||
},
|
||||
@@ -965,7 +973,7 @@ describe('convertAggregationToExpression', () => {
|
||||
dataSource: DataSource.LOGS,
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
expect(result).toStrictEqual([
|
||||
{
|
||||
expression: 'count()',
|
||||
},
|
||||
|
||||
@@ -471,6 +471,6 @@ describe('CheckboxFilter - User Flows', () => {
|
||||
|
||||
expect(filterForServiceName.key.key).toBe(SERVICE_NAME_KEY);
|
||||
expect(filterForServiceName.op).toBe('in');
|
||||
expect(filterForServiceName.value).toEqual(['mq-kafka', 'otel-demo']);
|
||||
expect(filterForServiceName.value).toStrictEqual(['mq-kafka', 'otel-demo']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
background: radial-gradient(circle, #fff 10%, transparent 0);
|
||||
background: radial-gradient(circle, var(--l1-foreground) 10%, transparent 0);
|
||||
background-size: 12px 12px;
|
||||
opacity: 1;
|
||||
|
||||
|
||||
@@ -323,7 +323,9 @@ describe('Quick Filters with custom filters', () => {
|
||||
const settingsButton = icon.closest('button') ?? icon;
|
||||
await user.click(settingsButton);
|
||||
|
||||
expect(await screen.findByText('Edit quick filters')).toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByText('Edit quick filters'),
|
||||
).resolves.toBeInTheDocument();
|
||||
|
||||
const addedSection = screen.getByText(ADDED_FILTERS_LABEL).parentElement!;
|
||||
expect(addedSection).toContainElement(
|
||||
@@ -454,7 +456,7 @@ describe('Quick Filters with custom filters', () => {
|
||||
});
|
||||
|
||||
const requestBody = putHandler.mock.calls[0][0];
|
||||
expect(requestBody.filters).toEqual(
|
||||
expect(requestBody.filters).toStrictEqual(
|
||||
expect.arrayContaining([
|
||||
expect.not.objectContaining({ key: FILTER_OS_DESCRIPTION }),
|
||||
]),
|
||||
@@ -535,12 +537,16 @@ describe('Quick Filters refetch behavior', () => {
|
||||
);
|
||||
|
||||
const { unmount } = render(<TestQuickFilters signal={SIGNAL} />);
|
||||
expect(await screen.findByText(FILTER_SERVICE_NAME)).toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByText(FILTER_SERVICE_NAME),
|
||||
).resolves.toBeInTheDocument();
|
||||
|
||||
unmount();
|
||||
|
||||
render(<TestQuickFilters signal={SIGNAL} />);
|
||||
expect(await screen.findByText(FILTER_SERVICE_NAME)).toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByText(FILTER_SERVICE_NAME),
|
||||
).resolves.toBeInTheDocument();
|
||||
|
||||
expect(getCalls).toBe(2);
|
||||
});
|
||||
@@ -578,7 +584,9 @@ describe('Quick Filters refetch behavior', () => {
|
||||
const user = userEvent.setup({ pointerEventsCheck: 0 });
|
||||
render(<TestQuickFilters signal={SIGNAL} />);
|
||||
|
||||
expect(await screen.findByText(FILTER_SERVICE_NAME)).toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByText(FILTER_SERVICE_NAME),
|
||||
).resolves.toBeInTheDocument();
|
||||
|
||||
const icon = await screen.findByTestId(SETTINGS_ICON_TEST_ID);
|
||||
const settingsButton = icon.closest('button') ?? icon;
|
||||
@@ -628,7 +636,9 @@ describe('Quick Filters refetch behavior', () => {
|
||||
const user = userEvent.setup({ pointerEventsCheck: 0 });
|
||||
render(<TestQuickFilters signal={SIGNAL} />);
|
||||
|
||||
expect(await screen.findByText(FILTER_SERVICE_NAME)).toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByText(FILTER_SERVICE_NAME),
|
||||
).resolves.toBeInTheDocument();
|
||||
|
||||
const icon = await screen.findByTestId(SETTINGS_ICON_TEST_ID);
|
||||
const settingsButton = icon.closest('button') ?? icon;
|
||||
@@ -657,6 +667,8 @@ describe('Quick Filters refetch behavior', () => {
|
||||
|
||||
render(<TestQuickFilters signal={SIGNAL} config={[]} />);
|
||||
|
||||
expect(await screen.findByText('No filters found')).toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByText('No filters found'),
|
||||
).resolves.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@ const testRoutes: RouteTabProps['routes'] = [
|
||||
];
|
||||
|
||||
describe('RouteTab component', () => {
|
||||
test('renders correctly', () => {
|
||||
it('renders correctly', () => {
|
||||
const history = createMemoryHistory();
|
||||
render(
|
||||
<Router history={history}>
|
||||
@@ -39,7 +39,7 @@ describe('RouteTab component', () => {
|
||||
expect(screen.getByRole('tab', { name: 'Tab2' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('renders correct number of tabs', () => {
|
||||
it('renders correct number of tabs', () => {
|
||||
const history = createMemoryHistory();
|
||||
render(
|
||||
<Router history={history}>
|
||||
@@ -47,10 +47,10 @@ describe('RouteTab component', () => {
|
||||
</Router>,
|
||||
);
|
||||
const tabs = screen.getAllByRole('tab');
|
||||
expect(tabs.length).toBe(testRoutes.length);
|
||||
expect(tabs).toHaveLength(testRoutes.length);
|
||||
});
|
||||
|
||||
test('sets provided activeKey as active tab', () => {
|
||||
it('sets provided activeKey as active tab', () => {
|
||||
const history = createMemoryHistory();
|
||||
render(
|
||||
<Router history={history}>
|
||||
@@ -62,7 +62,7 @@ describe('RouteTab component', () => {
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('navigates to correct route on tab click', () => {
|
||||
it('navigates to correct route on tab click', () => {
|
||||
const history = createMemoryHistory();
|
||||
render(
|
||||
<Router history={history}>
|
||||
@@ -74,7 +74,7 @@ describe('RouteTab component', () => {
|
||||
expect(history.location.pathname).toBe('/tab2');
|
||||
});
|
||||
|
||||
test('calls onChangeHandler on tab change', () => {
|
||||
it('calls onChangeHandler on tab change', () => {
|
||||
const onChangeHandler = jest.fn();
|
||||
const history = createMemoryHistory();
|
||||
render(
|
||||
|
||||
@@ -12,6 +12,12 @@
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&__layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&__tab-group {
|
||||
[data-slot='toggle-group'] {
|
||||
border-radius: 2px;
|
||||
|
||||
@@ -70,9 +70,9 @@ describe('EditKeyModal (URL-controlled)', () => {
|
||||
it('renders key data from prop when edit-key param is set', async () => {
|
||||
renderModal();
|
||||
|
||||
expect(
|
||||
await screen.findByDisplayValue('Original Key Name'),
|
||||
).toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByDisplayValue('Original Key Name'),
|
||||
).resolves.toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: /Save Changes/i })).toBeDisabled();
|
||||
});
|
||||
|
||||
@@ -111,7 +111,7 @@ describe('EditKeyModal (URL-controlled)', () => {
|
||||
|
||||
const latestUrlUpdate =
|
||||
onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]?.[0];
|
||||
expect(latestUrlUpdate).toEqual(
|
||||
expect(latestUrlUpdate).toStrictEqual(
|
||||
expect.objectContaining({
|
||||
queryString: expect.any(String),
|
||||
}),
|
||||
@@ -134,9 +134,9 @@ describe('EditKeyModal (URL-controlled)', () => {
|
||||
await user.click(screen.getByRole('button', { name: /Revoke Key/i }));
|
||||
|
||||
// Same dialog, now showing revoke confirmation
|
||||
expect(
|
||||
await screen.findByRole('dialog', { name: /Revoke Original Key Name/i }),
|
||||
).toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByRole('dialog', { name: /Revoke Original Key Name/i }),
|
||||
).resolves.toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(/Revoking this key will permanently invalidate it/i),
|
||||
).toBeInTheDocument();
|
||||
|
||||
@@ -104,7 +104,9 @@ describe('ServiceAccountDrawer', () => {
|
||||
it('renders Overview tab by default: editable name input, locked email, Save disabled when not dirty', async () => {
|
||||
renderDrawer();
|
||||
|
||||
expect(await screen.findByDisplayValue('CI Bot')).toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByDisplayValue('CI Bot'),
|
||||
).resolves.toBeInTheDocument();
|
||||
expect(screen.getByText('ci-bot@signoz.io')).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: /Save Changes/i })).toBeDisabled();
|
||||
});
|
||||
@@ -272,11 +274,11 @@ describe('ServiceAccountDrawer', () => {
|
||||
|
||||
renderDrawer();
|
||||
|
||||
expect(
|
||||
await screen.findByText(
|
||||
await expect(
|
||||
screen.findByText(
|
||||
/An unexpected error occurred while fetching service account details/i,
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
).resolves.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -349,11 +351,11 @@ describe('ServiceAccountDrawer – save-error UX', () => {
|
||||
await waitFor(() => expect(saveBtn).not.toBeDisabled());
|
||||
await user.click(saveBtn);
|
||||
|
||||
expect(
|
||||
await screen.findByText(/Name update.*name update failed/i, undefined, {
|
||||
await expect(
|
||||
screen.findByText(/Name update.*name update failed/i, undefined, {
|
||||
timeout: 5000,
|
||||
}),
|
||||
).toBeInTheDocument();
|
||||
).resolves.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('role add failure shows SaveErrorItem with the role name context', async () => {
|
||||
@@ -385,15 +387,11 @@ describe('ServiceAccountDrawer – save-error UX', () => {
|
||||
await waitFor(() => expect(saveBtn).not.toBeDisabled());
|
||||
await user.click(saveBtn);
|
||||
|
||||
expect(
|
||||
await screen.findByText(
|
||||
/Role 'signoz-viewer'.*role assign failed/i,
|
||||
undefined,
|
||||
{
|
||||
timeout: 5000,
|
||||
},
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByText(/Role 'signoz-viewer'.*role assign failed/i, undefined, {
|
||||
timeout: 5000,
|
||||
}),
|
||||
).resolves.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('role add retries on 429 then succeeds without showing an error', async () => {
|
||||
|
||||
@@ -197,17 +197,3 @@
|
||||
background-color: var(--l1-border);
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.sa-table {
|
||||
.ant-table-tbody {
|
||||
> tr.sa-table-row--tinted > td {
|
||||
background: rgba(0, 0, 0, 0.015);
|
||||
}
|
||||
|
||||
> tr:hover > td {
|
||||
background: rgba(0, 0, 0, 0.03) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,12 +147,12 @@
|
||||
left: 50%;
|
||||
width: 4px;
|
||||
transform: translateX(-50%);
|
||||
background: var(--l2-background);
|
||||
opacity: 1;
|
||||
pointer-events: none;
|
||||
transition:
|
||||
background 120ms ease,
|
||||
width 120ms ease;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.cursorColResize:hover .tanstackResizeHandleLine {
|
||||
|
||||
@@ -63,7 +63,9 @@ describe('TanStackCustomTableRow', () => {
|
||||
</tbody>
|
||||
</table>,
|
||||
);
|
||||
expect(await screen.findByTestId('mocked-row-cells')).toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByTestId('mocked-row-cells'),
|
||||
).resolves.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('applies active class when isRowActive returns true', () => {
|
||||
|
||||
@@ -183,7 +183,7 @@ describe('TanStackRowCells', () => {
|
||||
</tbody>
|
||||
</table>,
|
||||
);
|
||||
expect(await screen.findByText('expanded-r1')).toBeInTheDocument();
|
||||
await expect(screen.findByText('expanded-r1')).resolves.toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe('new tab click', () => {
|
||||
|
||||
@@ -36,7 +36,7 @@ describe('useColumnState', () => {
|
||||
renderHook(() => useColumnState({ storageKey: TEST_KEY, columns }));
|
||||
|
||||
const state = useColumnStore.getState().tables[TEST_KEY];
|
||||
expect(state.hiddenColumnIds).toEqual(['b']);
|
||||
expect(state.hiddenColumnIds).toStrictEqual(['b']);
|
||||
});
|
||||
|
||||
it('does not initialize without storageKey', () => {
|
||||
@@ -61,7 +61,7 @@ describe('useColumnState', () => {
|
||||
useColumnState({ storageKey: TEST_KEY, columns }),
|
||||
);
|
||||
|
||||
expect(result.current.columnVisibility).toEqual({ b: false });
|
||||
expect(result.current.columnVisibility).toStrictEqual({ b: false });
|
||||
});
|
||||
|
||||
it('applies visibilityBehavior for grouped state', () => {
|
||||
@@ -79,13 +79,15 @@ describe('useColumnState', () => {
|
||||
const { result: notGrouped } = renderHook(() =>
|
||||
useColumnState({ storageKey: TEST_KEY, columns, isGrouped: false }),
|
||||
);
|
||||
expect(notGrouped.current.columnVisibility).toEqual({ grouped: false });
|
||||
expect(notGrouped.current.columnVisibility).toStrictEqual({
|
||||
grouped: false,
|
||||
});
|
||||
|
||||
// Grouped
|
||||
const { result: grouped } = renderHook(() =>
|
||||
useColumnState({ storageKey: TEST_KEY, columns, isGrouped: true }),
|
||||
);
|
||||
expect(grouped.current.columnVisibility).toEqual({ ungrouped: false });
|
||||
expect(grouped.current.columnVisibility).toStrictEqual({ ungrouped: false });
|
||||
});
|
||||
|
||||
it('combines store hidden + visibilityBehavior', () => {
|
||||
@@ -103,7 +105,10 @@ describe('useColumnState', () => {
|
||||
useColumnState({ storageKey: TEST_KEY, columns, isGrouped: true }),
|
||||
);
|
||||
|
||||
expect(result.current.columnVisibility).toEqual({ a: false, b: false });
|
||||
expect(result.current.columnVisibility).toStrictEqual({
|
||||
a: false,
|
||||
b: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -119,7 +124,7 @@ describe('useColumnState', () => {
|
||||
useColumnState({ storageKey: TEST_KEY, columns }),
|
||||
);
|
||||
|
||||
expect(result.current.sortedColumns.map((c) => c.id)).toEqual([
|
||||
expect(result.current.sortedColumns.map((c) => c.id)).toStrictEqual([
|
||||
'a',
|
||||
'b',
|
||||
'c',
|
||||
@@ -138,7 +143,7 @@ describe('useColumnState', () => {
|
||||
useColumnState({ storageKey: TEST_KEY, columns }),
|
||||
);
|
||||
|
||||
expect(result.current.sortedColumns.map((c) => c.id)).toEqual([
|
||||
expect(result.current.sortedColumns.map((c) => c.id)).toStrictEqual([
|
||||
'c',
|
||||
'a',
|
||||
'b',
|
||||
@@ -157,7 +162,7 @@ describe('useColumnState', () => {
|
||||
useColumnState({ storageKey: TEST_KEY, columns }),
|
||||
);
|
||||
|
||||
expect(result.current.sortedColumns.map((c) => c.id)).toEqual([
|
||||
expect(result.current.sortedColumns.map((c) => c.id)).toStrictEqual([
|
||||
'pinned',
|
||||
'b',
|
||||
'a',
|
||||
@@ -181,7 +186,7 @@ describe('useColumnState', () => {
|
||||
result.current.hideColumn('a');
|
||||
});
|
||||
|
||||
expect(result.current.columnVisibility).toEqual({ a: false });
|
||||
expect(result.current.columnVisibility).toStrictEqual({ a: false });
|
||||
});
|
||||
|
||||
it('showColumn shows a column', () => {
|
||||
@@ -195,13 +200,13 @@ describe('useColumnState', () => {
|
||||
useColumnState({ storageKey: TEST_KEY, columns }),
|
||||
);
|
||||
|
||||
expect(result.current.columnVisibility).toEqual({ a: false });
|
||||
expect(result.current.columnVisibility).toStrictEqual({ a: false });
|
||||
|
||||
act(() => {
|
||||
result.current.showColumn('a');
|
||||
});
|
||||
|
||||
expect(result.current.columnVisibility).toEqual({});
|
||||
expect(result.current.columnVisibility).toStrictEqual({});
|
||||
});
|
||||
|
||||
it('setColumnSizing updates sizing', () => {
|
||||
@@ -219,7 +224,7 @@ describe('useColumnState', () => {
|
||||
result.current.setColumnSizing({ a: 200 });
|
||||
});
|
||||
|
||||
expect(result.current.columnSizing).toEqual({ a: 200 });
|
||||
expect(result.current.columnSizing).toStrictEqual({ a: 200 });
|
||||
});
|
||||
|
||||
it('setColumnOrder updates order from column array', () => {
|
||||
@@ -237,7 +242,7 @@ describe('useColumnState', () => {
|
||||
result.current.setColumnOrder([col('c'), col('a'), col('b')]);
|
||||
});
|
||||
|
||||
expect(result.current.sortedColumns.map((c) => c.id)).toEqual([
|
||||
expect(result.current.sortedColumns.map((c) => c.id)).toStrictEqual([
|
||||
'c',
|
||||
'a',
|
||||
'b',
|
||||
|
||||
@@ -29,9 +29,9 @@ describe('useColumnStore', () => {
|
||||
});
|
||||
|
||||
const state = useColumnStore.getState().tables[TEST_KEY];
|
||||
expect(state.hiddenColumnIds).toEqual(['b']);
|
||||
expect(state.columnOrder).toEqual([]);
|
||||
expect(state.columnSizing).toEqual({});
|
||||
expect(state.hiddenColumnIds).toStrictEqual(['b']);
|
||||
expect(state.columnOrder).toStrictEqual([]);
|
||||
expect(state.columnSizing).toStrictEqual({});
|
||||
});
|
||||
|
||||
it('does not reinitialize if already exists', () => {
|
||||
@@ -124,7 +124,9 @@ describe('useColumnStore', () => {
|
||||
.getState()
|
||||
.setColumnSizing(TEST_KEY, { col1: 200, col2: 300 });
|
||||
});
|
||||
expect(useColumnStore.getState().tables[TEST_KEY].columnSizing).toEqual({
|
||||
expect(
|
||||
useColumnStore.getState().tables[TEST_KEY].columnSizing,
|
||||
).toStrictEqual({
|
||||
col1: 200,
|
||||
col2: 300,
|
||||
});
|
||||
@@ -144,11 +146,9 @@ describe('useColumnStore', () => {
|
||||
.getState()
|
||||
.setColumnOrder(TEST_KEY, ['col2', 'col1', 'col3']);
|
||||
});
|
||||
expect(useColumnStore.getState().tables[TEST_KEY].columnOrder).toEqual([
|
||||
'col2',
|
||||
'col1',
|
||||
'col3',
|
||||
]);
|
||||
expect(useColumnStore.getState().tables[TEST_KEY].columnOrder).toStrictEqual(
|
||||
['col2', 'col1', 'col3'],
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -172,9 +172,9 @@ describe('useColumnStore', () => {
|
||||
});
|
||||
|
||||
const state = useColumnStore.getState().tables[TEST_KEY];
|
||||
expect(state.hiddenColumnIds).toEqual(['a']);
|
||||
expect(state.columnOrder).toEqual([]);
|
||||
expect(state.columnSizing).toEqual({});
|
||||
expect(state.hiddenColumnIds).toStrictEqual(['a']);
|
||||
expect(state.columnOrder).toStrictEqual([]);
|
||||
expect(state.columnSizing).toStrictEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -195,7 +195,7 @@ describe('useColumnStore', () => {
|
||||
});
|
||||
|
||||
const state = useColumnStore.getState().tables[TEST_KEY];
|
||||
expect(state.hiddenColumnIds).toEqual(['col1', 'col3']);
|
||||
expect(state.hiddenColumnIds).toStrictEqual(['col1', 'col3']);
|
||||
expect(state.hiddenColumnIds).not.toContain('col2');
|
||||
});
|
||||
|
||||
@@ -216,7 +216,7 @@ describe('useColumnStore', () => {
|
||||
});
|
||||
|
||||
const stateAfter = useColumnStore.getState().tables[TEST_KEY];
|
||||
expect(stateAfter.hiddenColumnIds).toEqual(hiddenBefore);
|
||||
expect(stateAfter.hiddenColumnIds).toStrictEqual(hiddenBefore);
|
||||
});
|
||||
|
||||
it('does nothing for unknown storage key', () => {
|
||||
@@ -242,7 +242,7 @@ describe('useColumnStore', () => {
|
||||
});
|
||||
|
||||
const { result } = renderHook(() => useHiddenColumnIds(TEST_KEY));
|
||||
expect(result.current).toEqual(['a']);
|
||||
expect(result.current).toStrictEqual(['a']);
|
||||
});
|
||||
|
||||
it('useHiddenColumnIds returns a stable snapshot for persisted state', () => {
|
||||
@@ -270,7 +270,7 @@ describe('useColumnStore', () => {
|
||||
});
|
||||
|
||||
const { result } = renderHook(() => useColumnSizing(TEST_KEY));
|
||||
expect(result.current).toEqual({ col1: 150 });
|
||||
expect(result.current).toStrictEqual({ col1: 150 });
|
||||
});
|
||||
|
||||
it('useColumnOrder returns order', () => {
|
||||
@@ -280,7 +280,7 @@ describe('useColumnStore', () => {
|
||||
});
|
||||
|
||||
const { result } = renderHook(() => useColumnOrder(TEST_KEY));
|
||||
expect(result.current).toEqual(['c', 'b', 'a']);
|
||||
expect(result.current).toStrictEqual(['c', 'b', 'a']);
|
||||
});
|
||||
|
||||
it('returns empty defaults for unknown storageKey', () => {
|
||||
@@ -288,9 +288,9 @@ describe('useColumnStore', () => {
|
||||
const { result: sizing } = renderHook(() => useColumnSizing('unknown'));
|
||||
const { result: order } = renderHook(() => useColumnOrder('unknown'));
|
||||
|
||||
expect(hidden.current).toEqual([]);
|
||||
expect(sizing.current).toEqual({});
|
||||
expect(order.current).toEqual([]);
|
||||
expect(hidden.current).toStrictEqual([]);
|
||||
expect(sizing.current).toStrictEqual({});
|
||||
expect(order.current).toStrictEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -80,7 +80,10 @@ describe('useTableParams (local mode — enableQueryParams not set)', () => {
|
||||
act(() => {
|
||||
result.current.setOrderBy({ columnName: 'cpu', order: 'desc' });
|
||||
});
|
||||
expect(result.current.orderBy).toEqual({ columnName: 'cpu', order: 'desc' });
|
||||
expect(result.current.orderBy).toStrictEqual({
|
||||
columnName: 'cpu',
|
||||
order: 'desc',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -143,7 +146,10 @@ describe('useTableParams (URL mode — enableQueryParams set)', () => {
|
||||
const orderBy = JSON.stringify({ columnName: 'name', order: 'desc' });
|
||||
const wrapper = createNuqsWrapper({ order_by: orderBy });
|
||||
const { result } = renderHook(() => useTableParams(true), { wrapper });
|
||||
expect(result.current.orderBy).toEqual({ columnName: 'name', order: 'desc' });
|
||||
expect(result.current.orderBy).toStrictEqual({
|
||||
columnName: 'name',
|
||||
order: 'desc',
|
||||
});
|
||||
});
|
||||
|
||||
it('updates URL when setPage is called', () => {
|
||||
@@ -178,7 +184,7 @@ describe('useTableParams (URL mode — enableQueryParams set)', () => {
|
||||
.filter(Boolean)
|
||||
.pop();
|
||||
expect(lastOrderBy).toBeDefined();
|
||||
expect(JSON.parse(lastOrderBy!)).toEqual({
|
||||
expect(JSON.parse(lastOrderBy!)).toStrictEqual({
|
||||
columnName: 'value',
|
||||
order: 'asc',
|
||||
});
|
||||
@@ -207,7 +213,7 @@ describe('useTableParams (URL mode — enableQueryParams set)', () => {
|
||||
result.current.setExpanded({ 'row-1': true });
|
||||
});
|
||||
|
||||
expect(result.current.expanded).toEqual({ 'row-1': true });
|
||||
expect(result.current.expanded).toStrictEqual({ 'row-1': true });
|
||||
});
|
||||
|
||||
it('toggles sort order correctly: null → asc → desc → null', () => {
|
||||
@@ -222,13 +228,19 @@ describe('useTableParams (URL mode — enableQueryParams set)', () => {
|
||||
act(() => {
|
||||
result.current.setOrderBy({ columnName: 'id', order: 'asc' });
|
||||
});
|
||||
expect(result.current.orderBy).toEqual({ columnName: 'id', order: 'asc' });
|
||||
expect(result.current.orderBy).toStrictEqual({
|
||||
columnName: 'id',
|
||||
order: 'asc',
|
||||
});
|
||||
|
||||
// Second click: asc → desc
|
||||
act(() => {
|
||||
result.current.setOrderBy({ columnName: 'id', order: 'desc' });
|
||||
});
|
||||
expect(result.current.orderBy).toEqual({ columnName: 'id', order: 'desc' });
|
||||
expect(result.current.orderBy).toStrictEqual({
|
||||
columnName: 'id',
|
||||
order: 'desc',
|
||||
});
|
||||
|
||||
// Third click: desc → null
|
||||
act(() => {
|
||||
|
||||
@@ -186,29 +186,3 @@
|
||||
letter-spacing: -0.06px;
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.warning-content {
|
||||
&__warning-code {
|
||||
color: var(--l2-foreground);
|
||||
}
|
||||
&__warning-message {
|
||||
color: var(--l1-foreground);
|
||||
}
|
||||
&__message-item {
|
||||
color: var(--l1-foreground);
|
||||
}
|
||||
&__message-badge {
|
||||
&-label-text {
|
||||
color: var(--l1-foreground);
|
||||
}
|
||||
.key-value-label__value {
|
||||
color: var(--l1-foreground);
|
||||
}
|
||||
}
|
||||
&__docs-button {
|
||||
background: var(--l1-background);
|
||||
color: var(--l2-foreground);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { formatUniversalUnit } from '../formatter';
|
||||
|
||||
describe('formatUniversalUnit', () => {
|
||||
describe('Time', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
// Days
|
||||
[31, UniversalYAxisUnit.DAYS, '4.43 weeks'],
|
||||
[7, UniversalYAxisUnit.DAYS, '1 week'],
|
||||
@@ -48,7 +48,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Data', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
// Bytes
|
||||
[864, UniversalYAxisUnit.BYTES, '864 B'],
|
||||
[1000, UniversalYAxisUnit.BYTES, '1 kB'],
|
||||
@@ -91,7 +91,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Data rate', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
// Bytes/second
|
||||
[864, UniversalYAxisUnit.BYTES_SECOND, '864 B/s'],
|
||||
[1000, UniversalYAxisUnit.BYTES_SECOND, '1 kB/s'],
|
||||
@@ -134,7 +134,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Bit', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
// Bits
|
||||
[1, UniversalYAxisUnit.BITS, '1 b'],
|
||||
[250, UniversalYAxisUnit.BITS, '250 b'],
|
||||
@@ -186,7 +186,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Bit rate', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
// Bits/second
|
||||
[512, UniversalYAxisUnit.BITS_SECOND, '512 b/s'],
|
||||
[1000, UniversalYAxisUnit.BITS_SECOND, '1 kb/s'],
|
||||
@@ -236,7 +236,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Count', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[100, UniversalYAxisUnit.COUNT, '100'],
|
||||
[875, UniversalYAxisUnit.COUNT, '875'],
|
||||
[1000, UniversalYAxisUnit.COUNT, '1 K'],
|
||||
@@ -256,7 +256,7 @@ describe('formatUniversalUnit', () => {
|
||||
expect(formatUniversalUnit(value, unit)).toBe(expected);
|
||||
});
|
||||
|
||||
test.each([
|
||||
it.each([
|
||||
[100, UniversalYAxisUnit.COUNT_SECOND, '100 c/s'],
|
||||
[875, UniversalYAxisUnit.COUNT_SECOND, '875 c/s'],
|
||||
[1000, UniversalYAxisUnit.COUNT_SECOND, '1K c/s'],
|
||||
@@ -267,7 +267,7 @@ describe('formatUniversalUnit', () => {
|
||||
expect(formatUniversalUnit(value, unit)).toBe(expected);
|
||||
});
|
||||
|
||||
test.each([
|
||||
it.each([
|
||||
[100, UniversalYAxisUnit.COUNT_MINUTE, '100 c/m'],
|
||||
[875, UniversalYAxisUnit.COUNT_MINUTE, '875 c/m'],
|
||||
[1000, UniversalYAxisUnit.COUNT_MINUTE, '1K c/m'],
|
||||
@@ -280,7 +280,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Operations units', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[780, UniversalYAxisUnit.OPS_SECOND, '780 ops/s'],
|
||||
[1000, UniversalYAxisUnit.OPS_SECOND, '1K ops/s'],
|
||||
[520, UniversalYAxisUnit.OPS_MINUTE, '520 ops/m'],
|
||||
@@ -297,7 +297,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Request units', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[615, UniversalYAxisUnit.REQUESTS_SECOND, '615 req/s'],
|
||||
[1000, UniversalYAxisUnit.REQUESTS_SECOND, '1K req/s'],
|
||||
[480, UniversalYAxisUnit.REQUESTS_MINUTE, '480 req/m'],
|
||||
@@ -311,7 +311,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Read/Write units', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[505, UniversalYAxisUnit.READS_SECOND, '505 rd/s'],
|
||||
[1000, UniversalYAxisUnit.READS_SECOND, '1K rd/s'],
|
||||
[610, UniversalYAxisUnit.WRITES_SECOND, '610 wr/s'],
|
||||
@@ -335,7 +335,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('IO Operations units', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[777, UniversalYAxisUnit.IOOPS_SECOND, '777 io/s'],
|
||||
[1000, UniversalYAxisUnit.IOOPS_SECOND, '1K io/s'],
|
||||
[2500, UniversalYAxisUnit.IOOPS_SECOND, '2.5K io/s'],
|
||||
@@ -363,7 +363,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Time (additional)', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[900, UniversalYAxisUnit.DURATION_MS, '900 milliseconds'],
|
||||
[1000, UniversalYAxisUnit.DURATION_MS, '1 second'],
|
||||
[1, UniversalYAxisUnit.DURATION_MS, '1 millisecond'],
|
||||
@@ -388,7 +388,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Data (IEC/Binary)', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
// Bytes
|
||||
[900, UniversalYAxisUnit.BYTES_IEC, '900 B'],
|
||||
[1024, UniversalYAxisUnit.BYTES_IEC, '1 KiB'],
|
||||
@@ -430,7 +430,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Data Rate (IEC/Binary)', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
// Kibibytes/second
|
||||
[900, UniversalYAxisUnit.KIBIBYTES_SECOND, '900 KiB/s'],
|
||||
[1024, UniversalYAxisUnit.KIBIBYTES_SECOND, '1 MiB/s'],
|
||||
@@ -473,7 +473,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Bits (IEC)', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[900, UniversalYAxisUnit.BITS_IEC, '900 b'],
|
||||
[1024, UniversalYAxisUnit.BITS_IEC, '1 Kib'],
|
||||
[1080, UniversalYAxisUnit.BITS_IEC, '1.05 Kib'],
|
||||
@@ -483,7 +483,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Hash Rate', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
// Hashes/second
|
||||
[412, UniversalYAxisUnit.HASH_RATE_HASHES_PER_SECOND, '412 H/s'],
|
||||
[1000, UniversalYAxisUnit.HASH_RATE_HASHES_PER_SECOND, '1 kH/s'],
|
||||
@@ -518,7 +518,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Miscellaneous', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[742, UniversalYAxisUnit.MISC_STRING, '742'],
|
||||
[688, UniversalYAxisUnit.MISC_SHORT, '688'],
|
||||
[555, UniversalYAxisUnit.MISC_HUMIDITY, '555 %H'],
|
||||
@@ -534,7 +534,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Acceleration', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[
|
||||
875,
|
||||
UniversalYAxisUnit.ACCELERATION_METERS_PER_SECOND_SQUARED,
|
||||
@@ -553,7 +553,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Angular', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[415, UniversalYAxisUnit.ANGULAR_DEGREE, '415 °'],
|
||||
[732, UniversalYAxisUnit.ANGULAR_RADIAN, '732 rad'],
|
||||
[128, UniversalYAxisUnit.ANGULAR_GRADIAN, '128 grad'],
|
||||
@@ -565,7 +565,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Area', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[210, UniversalYAxisUnit.AREA_SQUARE_METERS, '210 m²'],
|
||||
[152, UniversalYAxisUnit.AREA_SQUARE_FEET, '152 ft²'],
|
||||
[64, UniversalYAxisUnit.AREA_SQUARE_MILES, '64 mi²'],
|
||||
@@ -575,7 +575,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('FLOPs', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
// FLOPS
|
||||
[150, UniversalYAxisUnit.FLOPS_FLOPS, '150 FLOPS'],
|
||||
[1000, UniversalYAxisUnit.FLOPS_FLOPS, '1 kFLOPS'],
|
||||
@@ -613,7 +613,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Concentration', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[415, UniversalYAxisUnit.CONCENTRATION_PPM, '415 ppm'],
|
||||
[1000, UniversalYAxisUnit.CONCENTRATION_PPM, '1000 ppm'],
|
||||
[732, UniversalYAxisUnit.CONCENTRATION_PPB, '732 ppb'],
|
||||
@@ -650,7 +650,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Currency', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[812, UniversalYAxisUnit.CURRENCY_USD, '$812'],
|
||||
[645, UniversalYAxisUnit.CURRENCY_GBP, '£645'],
|
||||
[731, UniversalYAxisUnit.CURRENCY_EUR, '€731'],
|
||||
@@ -688,7 +688,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Power/Electrical', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[715, UniversalYAxisUnit.POWER_WATT, '715 W'],
|
||||
[1000, UniversalYAxisUnit.POWER_WATT, '1 kW'],
|
||||
[1080, UniversalYAxisUnit.POWER_WATT, '1.08 kW'],
|
||||
@@ -744,7 +744,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Flow', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[512, UniversalYAxisUnit.FLOW_GALLONS_PER_MINUTE, '512 gpm'],
|
||||
[1000, UniversalYAxisUnit.FLOW_GALLONS_PER_MINUTE, '1000 gpm'],
|
||||
[678, UniversalYAxisUnit.FLOW_CUBIC_METERS_PER_SECOND, '678 cms'],
|
||||
@@ -766,7 +766,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Force', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[845, UniversalYAxisUnit.FORCE_NEWTON_METERS, '845 Nm'],
|
||||
[1000, UniversalYAxisUnit.FORCE_NEWTON_METERS, '1 kNm'],
|
||||
[1080, UniversalYAxisUnit.FORCE_NEWTON_METERS, '1.08 kNm'],
|
||||
@@ -782,7 +782,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Mass', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[120, UniversalYAxisUnit.MASS_MILLIGRAM, '120 mg'],
|
||||
[120000, UniversalYAxisUnit.MASS_MILLIGRAM, '120 g'],
|
||||
[987, UniversalYAxisUnit.MASS_GRAM, '987 g'],
|
||||
@@ -796,7 +796,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Length', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[88, UniversalYAxisUnit.LENGTH_MILLIMETER, '88 mm'],
|
||||
[100, UniversalYAxisUnit.LENGTH_MILLIMETER, '100 mm'],
|
||||
[1000, UniversalYAxisUnit.LENGTH_MILLIMETER, '1 m'],
|
||||
@@ -812,7 +812,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Pressure', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[45, UniversalYAxisUnit.PRESSURE_MILLIBAR, '45 mbar'],
|
||||
[1013, UniversalYAxisUnit.PRESSURE_MILLIBAR, '1.01 bar'],
|
||||
[27, UniversalYAxisUnit.PRESSURE_BAR, '27 bar'],
|
||||
@@ -828,7 +828,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Radiation', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[452, UniversalYAxisUnit.RADIATION_BECQUEREL, '452 Bq'],
|
||||
[37, UniversalYAxisUnit.RADIATION_CURIE, '37 Ci'],
|
||||
[128, UniversalYAxisUnit.RADIATION_GRAY, '128 Gy'],
|
||||
@@ -849,7 +849,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Rotation Speed', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[345, UniversalYAxisUnit.ROTATION_SPEED_REVOLUTIONS_PER_MINUTE, '345 rpm'],
|
||||
[789, UniversalYAxisUnit.ROTATION_SPEED_HERTZ, '789 Hz'],
|
||||
[789000, UniversalYAxisUnit.ROTATION_SPEED_HERTZ, '789 kHz'],
|
||||
@@ -861,7 +861,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Temperature', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[37, UniversalYAxisUnit.TEMPERATURE_CELSIUS, '37 °C'],
|
||||
[451, UniversalYAxisUnit.TEMPERATURE_FAHRENHEIT, '451 °F'],
|
||||
[310, UniversalYAxisUnit.TEMPERATURE_KELVIN, '310 K'],
|
||||
@@ -871,7 +871,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Velocity', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[900, UniversalYAxisUnit.VELOCITY_METERS_PER_SECOND, '900 m/s'],
|
||||
[456, UniversalYAxisUnit.VELOCITY_KILOMETERS_PER_HOUR, '456 km/h'],
|
||||
[789, UniversalYAxisUnit.VELOCITY_MILES_PER_HOUR, '789 mph'],
|
||||
@@ -882,7 +882,7 @@ describe('formatUniversalUnit', () => {
|
||||
});
|
||||
|
||||
describe('Volume', () => {
|
||||
test.each([
|
||||
it.each([
|
||||
[1200, UniversalYAxisUnit.VOLUME_MILLILITER, '1.2 L'],
|
||||
[9000000, UniversalYAxisUnit.VOLUME_MILLILITER, '9 kL'],
|
||||
[9, UniversalYAxisUnit.VOLUME_LITER, '9 L'],
|
||||
|
||||
@@ -16,8 +16,8 @@ describe('YAxisUnitSelector utils', () => {
|
||||
|
||||
it('returns null or self for unknown units', () => {
|
||||
expect(mapMetricUnitToUniversalUnit('unknown_unit')).toBe('unknown_unit');
|
||||
expect(mapMetricUnitToUniversalUnit('')).toBe(null);
|
||||
expect(mapMetricUnitToUniversalUnit(undefined)).toBe(null);
|
||||
expect(mapMetricUnitToUniversalUnit('')).toBeNull();
|
||||
expect(mapMetricUnitToUniversalUnit(undefined)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -62,7 +62,7 @@ describe('YAxisUnitSelector utils', () => {
|
||||
},
|
||||
];
|
||||
const mergedCategories = mergeCategories(categories1, categories2);
|
||||
expect(mergedCategories).toEqual([
|
||||
expect(mergedCategories).toStrictEqual([
|
||||
{
|
||||
name: YAxisCategoryNames.Data,
|
||||
units: [
|
||||
|
||||
@@ -149,7 +149,7 @@ describe('CmdKPalette', () => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('renders navigation and settings groups and items', () => {
|
||||
it('renders navigation and settings groups and items', () => {
|
||||
render(<CmdKPalette userRole="ADMIN" />);
|
||||
|
||||
expect(screen.getByText('Navigation')).toBeInTheDocument();
|
||||
@@ -160,7 +160,7 @@ describe('CmdKPalette', () => {
|
||||
expect(screen.getByText('Switch to Dark Mode')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('clicking a navigation item calls history.push with correct route', async () => {
|
||||
it('clicking a navigation item calls history.push with correct route', async () => {
|
||||
const user = userEvent.setup({ pointerEventsCheck: 0 });
|
||||
render(<CmdKPalette userRole="ADMIN" />);
|
||||
|
||||
@@ -170,14 +170,14 @@ describe('CmdKPalette', () => {
|
||||
expect(history.push).toHaveBeenCalledWith(ROUTES.HOME);
|
||||
});
|
||||
|
||||
test('role-based filtering (basic smoke)', () => {
|
||||
it('role-based filtering (basic smoke)', () => {
|
||||
render(<CmdKPalette userRole="VIEWER" />);
|
||||
|
||||
// VIEWER still sees basic navigation items
|
||||
expect(screen.getByText(HOME_LABEL)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('keyboard shortcut opens palette via setOpen', () => {
|
||||
it('keyboard shortcut opens palette via setOpen', () => {
|
||||
render(<CmdKPalette userRole="ADMIN" />);
|
||||
|
||||
const event = new KeyboardEvent('keydown', { key: 'k', ctrlKey: true });
|
||||
@@ -186,7 +186,7 @@ describe('CmdKPalette', () => {
|
||||
expect(mockSetOpen).toHaveBeenCalledWith(true);
|
||||
});
|
||||
|
||||
test('items render with icons when provided', () => {
|
||||
it('items render with icons when provided', () => {
|
||||
render(<CmdKPalette userRole="ADMIN" />);
|
||||
|
||||
const iconHolders = document.querySelectorAll('.cmd-item-icon');
|
||||
@@ -194,7 +194,7 @@ describe('CmdKPalette', () => {
|
||||
expect(screen.getByText(HOME_LABEL)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('closing the palette via handleInvoke sets open to false', async () => {
|
||||
it('closing the palette via handleInvoke sets open to false', async () => {
|
||||
const user = userEvent.setup({ pointerEventsCheck: 0 });
|
||||
render(<CmdKPalette userRole="ADMIN" />);
|
||||
|
||||
|
||||
@@ -9,4 +9,5 @@ export enum FeatureKeys {
|
||||
ANOMALY_DETECTION = 'anomaly_detection',
|
||||
ONBOARDING_V3 = 'onboarding_v3',
|
||||
DOT_METRICS_ENABLED = 'dot_metrics_enabled',
|
||||
BODY_JSON_ENABLED = 'body_json_enabled',
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ const ROUTES = {
|
||||
HOME_PAGE: '/',
|
||||
PUBLIC_DASHBOARD: '/public/dashboard/:dashboardId',
|
||||
SERVICE_ACCOUNTS_SETTINGS: '/settings/service-accounts',
|
||||
MCP_SERVER: '/settings/mcp-server',
|
||||
} as const;
|
||||
|
||||
export default ROUTES;
|
||||
|
||||
@@ -157,9 +157,3 @@
|
||||
.view-all-drawer {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.ant-table {
|
||||
background: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,13 +34,13 @@ describe('Alert Channels Settings List page', () => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
describe('Should display the Alert Channels page properly', () => {
|
||||
it('Should check if "The alerts will be sent to all the configured channels." is visible ', () => {
|
||||
it('Should check if "The alerts will be sent to all the configured channels." is visible', () => {
|
||||
expect(screen.getByText('sending_channels_note')).toBeInTheDocument();
|
||||
});
|
||||
it('Should check if "New Alert Channel" Button is visble ', () => {
|
||||
it('Should check if "New Alert Channel" Button is visble', () => {
|
||||
expect(screen.getByText('button_new_channel')).toBeInTheDocument();
|
||||
});
|
||||
it('Should check if the help icon is visible and displays "tooltip_notification_channels ', async () => {
|
||||
it('Should check if the help icon is visible and displays "tooltip_notification_channels', async () => {
|
||||
const helpIcon = screen.getByLabelText('question-circle');
|
||||
|
||||
fireEvent.mouseOver(helpIcon);
|
||||
|
||||
@@ -38,7 +38,7 @@ describe('Alert Channels Settings List page (Normal User)', () => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
describe('Should display the Alert Channels page properly', () => {
|
||||
it('Should check if "The alerts will be sent to all the configured channels." is visible ', async () => {
|
||||
it('Should check if "The alerts will be sent to all the configured channels." is visible', async () => {
|
||||
await waitFor(() =>
|
||||
expect(screen.getByText('sending_channels_note')).toBeInTheDocument(),
|
||||
);
|
||||
@@ -51,7 +51,7 @@ describe('Alert Channels Settings List page (Normal User)', () => {
|
||||
await waitFor(() => expect(newAlertButton).toBeInTheDocument());
|
||||
expect(newAlertButton).toBeDisabled();
|
||||
});
|
||||
it('Should check if the help icon is visible and displays "tooltip_notification_channels ', async () => {
|
||||
it('Should check if the help icon is visible and displays "tooltip_notification_channels', async () => {
|
||||
const helpIcon = screen.getByLabelText('question-circle');
|
||||
fireEvent.mouseOver(helpIcon);
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ describe('Create Alert Channel', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
describe('Should check if the new alert channel is properly displayed with the cascading fields of slack channel ', () => {
|
||||
describe('Should check if the new alert channel is properly displayed with the cascading fields of slack channel', () => {
|
||||
beforeEach(() => {
|
||||
render(<CreateAlertChannels preType={ChannelType.Slack} />);
|
||||
});
|
||||
@@ -54,13 +54,13 @@ describe('Create Alert Channel', () => {
|
||||
it('Should check if the title is "New Notification Channels"', () => {
|
||||
expect(screen.getByText('page_title_create')).toBeInTheDocument();
|
||||
});
|
||||
it('Should check if the name label and textbox are displayed properly ', () => {
|
||||
it('Should check if the name label and textbox are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_channel_name',
|
||||
testId: 'channel-name-textbox',
|
||||
});
|
||||
});
|
||||
it('Should check if Send resolved alerts label and checkbox are displayed properly ', () => {
|
||||
it('Should check if Send resolved alerts label and checkbox are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_send_resolved',
|
||||
testId: 'field-send-resolved-checkbox',
|
||||
@@ -76,13 +76,13 @@ describe('Create Alert Channel', () => {
|
||||
it('Should check if the selected item in the type dropdown has text "Slack"', () => {
|
||||
expect(screen.getByText('Slack')).toBeInTheDocument();
|
||||
});
|
||||
it('Should check if Webhook URL label and input are displayed properly ', () => {
|
||||
it('Should check if Webhook URL label and input are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_webhook_url',
|
||||
testId: 'webhook-url-textbox',
|
||||
});
|
||||
});
|
||||
it('Should check if Recepient label, input, and help text are displayed properly ', () => {
|
||||
it('Should check if Recepient label, input, and help text are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_slack_recipient',
|
||||
testId: 'slack-channel-textbox',
|
||||
@@ -90,7 +90,7 @@ describe('Create Alert Channel', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('Should check if Title label and text area are displayed properly ', () => {
|
||||
it('Should check if Title label and text area are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_slack_title',
|
||||
testId: 'title-textarea',
|
||||
@@ -101,7 +101,7 @@ describe('Create Alert Channel', () => {
|
||||
|
||||
expect(titleTextArea).toHaveTextContent(slackTitleDefaultValue);
|
||||
});
|
||||
it('Should check if Description label and text area are displayed properly ', () => {
|
||||
it('Should check if Description label and text area are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_slack_description',
|
||||
testId: 'description-textarea',
|
||||
@@ -177,13 +177,13 @@ describe('Create Alert Channel', () => {
|
||||
it('Should check if the selected item in the type dropdown has text "Webhook"', () => {
|
||||
expect(screen.getByText('Webhook')).toBeInTheDocument();
|
||||
});
|
||||
it('Should check if Webhook URL label and input are displayed properly ', () => {
|
||||
it('Should check if Webhook URL label and input are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_webhook_url',
|
||||
testId: 'webhook-url-textbox',
|
||||
});
|
||||
});
|
||||
it('Should check if Webhook User Name label, input, and help text are displayed properly ', () => {
|
||||
it('Should check if Webhook User Name label, input, and help text are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_webhook_username',
|
||||
testId: 'webhook-username-textbox',
|
||||
@@ -321,7 +321,7 @@ describe('Create Alert Channel', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('Should check if Message contains the default template ', () => {
|
||||
it('Should check if Message contains the default template', () => {
|
||||
const messageTextArea = screen.getByTestId('opsgenie-message-textarea');
|
||||
|
||||
expect(messageTextArea).toHaveValue(opsGenieMessageDefaultValue);
|
||||
@@ -387,14 +387,14 @@ describe('Create Alert Channel', () => {
|
||||
expect(screen.getByText('Microsoft Teams')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should check if Webhook URL label and input are displayed properly ', () => {
|
||||
it('Should check if Webhook URL label and input are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_webhook_url',
|
||||
testId: 'webhook-url-textbox',
|
||||
});
|
||||
});
|
||||
|
||||
it('Should check if Title label and text area are displayed properly ', () => {
|
||||
it('Should check if Title label and text area are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_slack_title',
|
||||
testId: 'title-textarea',
|
||||
@@ -406,7 +406,7 @@ describe('Create Alert Channel', () => {
|
||||
|
||||
expect(titleTextArea).toHaveTextContent(slackTitleDefaultValue);
|
||||
});
|
||||
it('Should check if Description label and text area are displayed properly ', () => {
|
||||
it('Should check if Description label and text area are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_slack_description',
|
||||
testId: 'description-textarea',
|
||||
|
||||
@@ -23,20 +23,20 @@ describe('Create Alert Channel (Normal User)', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
describe('Should check if the new alert channel is properly displayed with the cascading fields of slack channel ', () => {
|
||||
describe('Should check if the new alert channel is properly displayed with the cascading fields of slack channel', () => {
|
||||
beforeEach(() => {
|
||||
render(<CreateAlertChannels preType={ChannelType.Slack} />);
|
||||
});
|
||||
it('Should check if the title is "New Notification Channels"', () => {
|
||||
expect(screen.getByText('page_title_create')).toBeInTheDocument();
|
||||
});
|
||||
it('Should check if the name label and textbox are displayed properly ', () => {
|
||||
it('Should check if the name label and textbox are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_channel_name',
|
||||
testId: 'channel-name-textbox',
|
||||
});
|
||||
});
|
||||
it('Should check if Send resolved alerts label and checkbox are displayed properly ', () => {
|
||||
it('Should check if Send resolved alerts label and checkbox are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_send_resolved',
|
||||
testId: 'field-send-resolved-checkbox',
|
||||
@@ -52,13 +52,13 @@ describe('Create Alert Channel (Normal User)', () => {
|
||||
it('Should check if the selected item in the type dropdown has text "Slack"', () => {
|
||||
expect(screen.getByText('Slack')).toBeInTheDocument();
|
||||
});
|
||||
it('Should check if Webhook URL label and input are displayed properly ', () => {
|
||||
it('Should check if Webhook URL label and input are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_webhook_url',
|
||||
testId: 'webhook-url-textbox',
|
||||
});
|
||||
});
|
||||
it('Should check if Recepient label, input, and help text are displayed properly ', () => {
|
||||
it('Should check if Recepient label, input, and help text are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_slack_recipient',
|
||||
testId: 'slack-channel-textbox',
|
||||
@@ -66,7 +66,7 @@ describe('Create Alert Channel (Normal User)', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('Should check if Title label and text area are displayed properly ', () => {
|
||||
it('Should check if Title label and text area are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_slack_title',
|
||||
testId: 'title-textarea',
|
||||
@@ -77,7 +77,7 @@ describe('Create Alert Channel (Normal User)', () => {
|
||||
|
||||
expect(titleTextArea).toHaveTextContent(slackTitleDefaultValue);
|
||||
});
|
||||
it('Should check if Description label and text area are displayed properly ', () => {
|
||||
it('Should check if Description label and text area are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_slack_description',
|
||||
testId: 'description-textarea',
|
||||
@@ -103,13 +103,13 @@ describe('Create Alert Channel (Normal User)', () => {
|
||||
it('Should check if the selected item in the type dropdown has text "Webhook"', () => {
|
||||
expect(screen.getByText('Webhook')).toBeInTheDocument();
|
||||
});
|
||||
it('Should check if Webhook URL label and input are displayed properly ', () => {
|
||||
it('Should check if Webhook URL label and input are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_webhook_url',
|
||||
testId: 'webhook-url-textbox',
|
||||
});
|
||||
});
|
||||
it('Should check if Webhook User Name label, input, and help text are displayed properly ', () => {
|
||||
it('Should check if Webhook User Name label, input, and help text are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_webhook_username',
|
||||
testId: 'webhook-username-textbox',
|
||||
@@ -247,7 +247,7 @@ describe('Create Alert Channel (Normal User)', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('Should check if Message contains the default template ', () => {
|
||||
it('Should check if Message contains the default template', () => {
|
||||
const messageTextArea = screen.getByTestId('opsgenie-message-textarea');
|
||||
|
||||
expect(messageTextArea).toHaveValue(opsGenieMessageDefaultValue);
|
||||
|
||||
@@ -24,7 +24,7 @@ jest.mock('components/MarkdownRenderer/MarkdownRenderer', () => ({
|
||||
MarkdownRenderer: jest.fn(() => <div>Mocked MarkdownRenderer</div>),
|
||||
}));
|
||||
|
||||
describe('Should check if the edit alert channel is properly displayed ', () => {
|
||||
describe('Should check if the edit alert channel is properly displayed', () => {
|
||||
beforeEach(() => {
|
||||
render(<EditAlertChannels initialValue={editAlertChannelInitialValue} />);
|
||||
});
|
||||
@@ -35,14 +35,14 @@ describe('Should check if the edit alert channel is properly displayed ', () =>
|
||||
expect(screen.getByText('page_title_edit')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should check if the name label and textbox are displayed properly ', () => {
|
||||
it('Should check if the name label and textbox are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_channel_name',
|
||||
testId: 'channel-name-textbox',
|
||||
value: 'Dummy-Channel',
|
||||
});
|
||||
});
|
||||
it('Should check if Send resolved alerts label and checkbox are displayed properly and the checkbox is checked ', () => {
|
||||
it('Should check if Send resolved alerts label and checkbox are displayed properly and the checkbox is checked', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_send_resolved',
|
||||
testId: 'field-send-resolved-checkbox',
|
||||
@@ -61,7 +61,7 @@ describe('Should check if the edit alert channel is properly displayed ', () =>
|
||||
expect(screen.getByText('Slack')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should check if Webhook URL label and input are displayed properly ', () => {
|
||||
it('Should check if Webhook URL label and input are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_webhook_url',
|
||||
testId: 'webhook-url-textbox',
|
||||
@@ -70,7 +70,7 @@ describe('Should check if the edit alert channel is properly displayed ', () =>
|
||||
});
|
||||
});
|
||||
|
||||
it('Should check if Recepient label, input, and help text are displayed properly ', () => {
|
||||
it('Should check if Recepient label, input, and help text are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_slack_recipient',
|
||||
testId: 'slack-channel-textbox',
|
||||
@@ -79,7 +79,7 @@ describe('Should check if the edit alert channel is properly displayed ', () =>
|
||||
});
|
||||
});
|
||||
|
||||
it('Should check if Title label and text area are displayed properly ', () => {
|
||||
it('Should check if Title label and text area are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_slack_title',
|
||||
testId: 'title-textarea',
|
||||
@@ -92,7 +92,7 @@ describe('Should check if the edit alert channel is properly displayed ', () =>
|
||||
expect(titleTextArea).toHaveTextContent(slackTitleDefaultValue);
|
||||
});
|
||||
|
||||
it('Should check if Description label and text area are displayed properly ', () => {
|
||||
it('Should check if Description label and text area are displayed properly', () => {
|
||||
testLabelInputAndHelpValue({
|
||||
labelText: 'field_slack_description',
|
||||
testId: 'description-textarea',
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
} from './utils';
|
||||
|
||||
describe('Error utils', () => {
|
||||
test('Valid OrderBy Params', () => {
|
||||
it('Valid OrderBy Params', () => {
|
||||
expect(isOrderParams('serviceName')).toBe(true);
|
||||
expect(isOrderParams('exceptionCount')).toBe(true);
|
||||
expect(isOrderParams('lastSeen')).toBe(true);
|
||||
@@ -20,24 +20,24 @@ describe('Error utils', () => {
|
||||
expect(isOrderParams('exceptionType')).toBe(true);
|
||||
});
|
||||
|
||||
test('Invalid OrderBy Params', () => {
|
||||
it('Invalid OrderBy Params', () => {
|
||||
expect(isOrderParams('invalid')).toBe(false);
|
||||
expect(isOrderParams(null)).toBe(false);
|
||||
expect(isOrderParams('')).toBe(false);
|
||||
});
|
||||
|
||||
test('Valid Order', () => {
|
||||
it('Valid Order', () => {
|
||||
expect(isOrder('ascending')).toBe(true);
|
||||
expect(isOrder('descending')).toBe(true);
|
||||
});
|
||||
|
||||
test('Invalid Order', () => {
|
||||
it('Invalid Order', () => {
|
||||
expect(isOrder('invalid')).toBe(false);
|
||||
expect(isOrder(null)).toBe(false);
|
||||
expect(isOrder('')).toBe(false);
|
||||
});
|
||||
|
||||
test('Default Order', () => {
|
||||
it('Default Order', () => {
|
||||
const OrderBy: OrderBy[] = [
|
||||
'exceptionCount',
|
||||
'exceptionType',
|
||||
@@ -57,7 +57,7 @@ describe('Error utils', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('Limit', () => {
|
||||
it('Limit', () => {
|
||||
expect(getLimit(null)).toBe(10);
|
||||
expect(getLimit('')).toBe(10);
|
||||
expect(getLimit('0')).toBe(0);
|
||||
@@ -68,7 +68,7 @@ describe('Error utils', () => {
|
||||
expect(getLimit('101')).toBe(101);
|
||||
});
|
||||
|
||||
test('Update Page Size', () => {
|
||||
it('Update Page Size', () => {
|
||||
expect(getUpdatePageSize(null)).toBe(10);
|
||||
expect(getUpdatePageSize('')).toBe(10);
|
||||
expect(getUpdatePageSize('0')).toBe(0);
|
||||
@@ -79,7 +79,7 @@ describe('Error utils', () => {
|
||||
expect(getUpdatePageSize('101')).toBe(101);
|
||||
});
|
||||
|
||||
test('Order Params', () => {
|
||||
it('Order Params', () => {
|
||||
expect(getOrderParams(null)).toBe('serviceName');
|
||||
expect(getOrderParams('')).toBe('serviceName');
|
||||
expect(getOrderParams('serviceName')).toBe('serviceName');
|
||||
@@ -89,7 +89,7 @@ describe('Error utils', () => {
|
||||
expect(getOrderParams('exceptionType')).toBe('exceptionType');
|
||||
});
|
||||
|
||||
test('OffSet', () => {
|
||||
it('OffSet', () => {
|
||||
expect(getOffSet(null)).toBe(0);
|
||||
expect(getOffSet('')).toBe(0);
|
||||
expect(getOffSet('0')).toBe(0);
|
||||
@@ -100,7 +100,7 @@ describe('Error utils', () => {
|
||||
expect(getOffSet('101')).toBe(101);
|
||||
});
|
||||
|
||||
test('Order', () => {
|
||||
it('Order', () => {
|
||||
expect(getOrder(null)).toBe('ascending');
|
||||
expect(getOrder('')).toBe('ascending');
|
||||
expect(getOrder('ascending')).toBe('ascending');
|
||||
|
||||
@@ -30,18 +30,18 @@ function UplotChart({
|
||||
|
||||
useEffect(() => {
|
||||
if (plotInstance.current) {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
plotInstance.current.destroy();
|
||||
}
|
||||
|
||||
if (data && data.length > 0) {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
plotInstance.current = new uPlot(options, data, chartRef.current);
|
||||
}
|
||||
|
||||
return (): void => {
|
||||
if (plotInstance.current) {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
plotInstance.current.destroy();
|
||||
}
|
||||
};
|
||||
@@ -275,7 +275,7 @@ function AnomalyAlertEvaluationView({
|
||||
};
|
||||
|
||||
const handleSearchValueChange = useDebouncedFn((event): void => {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
const value = event?.target?.value || '';
|
||||
|
||||
handleSearch(value);
|
||||
|
||||
@@ -233,7 +233,7 @@ describe('DomainMetrics - V5 Query Payload Tests', () => {
|
||||
// Wait for skeletons to disappear
|
||||
await waitFor(() => {
|
||||
const skeletons = document.querySelectorAll('.ant-skeleton-button');
|
||||
expect(skeletons.length).toBe(0);
|
||||
expect(skeletons).toHaveLength(0);
|
||||
});
|
||||
|
||||
// Verify all metric labels are displayed
|
||||
@@ -272,7 +272,7 @@ describe('DomainMetrics - V5 Query Payload Tests', () => {
|
||||
|
||||
await waitFor(() => {
|
||||
const skeletons = document.querySelectorAll('.ant-skeleton-button');
|
||||
expect(skeletons.length).toBe(0);
|
||||
expect(skeletons).toHaveLength(0);
|
||||
});
|
||||
|
||||
// When no data, all values should show "-"
|
||||
|
||||
@@ -303,7 +303,7 @@ describe('EndPointMetrics - V5 Query Payload Tests', () => {
|
||||
// Wait for skeletons to disappear
|
||||
await waitFor(() => {
|
||||
const skeletons = document.querySelectorAll('.ant-skeleton-button');
|
||||
expect(skeletons.length).toBe(0);
|
||||
expect(skeletons).toHaveLength(0);
|
||||
});
|
||||
|
||||
// Verify all metric labels are displayed
|
||||
@@ -342,7 +342,7 @@ describe('EndPointMetrics - V5 Query Payload Tests', () => {
|
||||
|
||||
await waitFor(() => {
|
||||
const skeletons = document.querySelectorAll('.ant-skeleton-button');
|
||||
expect(skeletons.length).toBe(0);
|
||||
expect(skeletons).toHaveLength(0);
|
||||
});
|
||||
|
||||
// When no data, all values should show "-"
|
||||
|
||||
@@ -226,54 +226,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.api-quick-filter-left-section {
|
||||
.api-quick-filters-header {
|
||||
border-bottom: 1px solid var(--bg-vanilla-300);
|
||||
}
|
||||
}
|
||||
|
||||
.api-module-right-section {
|
||||
.toolbar {
|
||||
border-bottom: 1px solid var(--bg-vanilla-300);
|
||||
}
|
||||
}
|
||||
|
||||
.no-filtered-domains-message-container {
|
||||
.no-filtered-domains-message-content {
|
||||
.no-filtered-domains-message {
|
||||
.no-domain-title {
|
||||
color: var(--l1-foreground);
|
||||
}
|
||||
|
||||
.no-domain-subtitle {
|
||||
color: var(--l2-foreground);
|
||||
|
||||
.attribute {
|
||||
font-family: 'Space Mono';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.api-monitoring-domain-list-table {
|
||||
.ant-table {
|
||||
.ant-table-cell {
|
||||
color: var(--l1-foreground);
|
||||
}
|
||||
|
||||
.table-row-light {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.table-row-dark {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.round-metric-tag {
|
||||
color: var(--l1-foreground);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,7 +303,7 @@ describe('API Monitoring Utils', () => {
|
||||
const result = extractPortAndEndpoint(url);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
port: '8080',
|
||||
endpoint: '/api/endpoint?param=value',
|
||||
});
|
||||
@@ -317,7 +317,7 @@ describe('API Monitoring Utils', () => {
|
||||
const result = extractPortAndEndpoint(url);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
port: '-',
|
||||
endpoint: '/api/endpoint',
|
||||
});
|
||||
@@ -331,7 +331,7 @@ describe('API Monitoring Utils', () => {
|
||||
const result = extractPortAndEndpoint(nonUrl);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
port: '-',
|
||||
endpoint: nonUrl,
|
||||
});
|
||||
@@ -379,7 +379,7 @@ describe('API Monitoring Utils', () => {
|
||||
const result = getFormattedEndPointDropDownData([]);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual([]);
|
||||
expect(result).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('should handle undefined input', () => {
|
||||
@@ -392,7 +392,7 @@ describe('API Monitoring Utils', () => {
|
||||
// Assert
|
||||
// If the implementation doesn't handle undefined, just check that it returns something predictable
|
||||
// Based on the error, it seems the function returns undefined for undefined input
|
||||
expect(result).toEqual([]);
|
||||
expect(result).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('should handle items without URL path', () => {
|
||||
@@ -460,7 +460,7 @@ describe('API Monitoring Utils', () => {
|
||||
|
||||
// Assert
|
||||
expect(result).toBeDefined();
|
||||
expect(result.length).toBe(2);
|
||||
expect(result).toHaveLength(2);
|
||||
|
||||
// Check first item
|
||||
expect(result[0].statusCode).toBe('200');
|
||||
@@ -493,7 +493,7 @@ describe('API Monitoring Utils', () => {
|
||||
|
||||
// Assert
|
||||
expect(result).toBeDefined();
|
||||
expect(result.length).toBe(1);
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].statusCode).toBe('-');
|
||||
expect(result[0].count).toBe('-');
|
||||
expect(result[0].p99Latency).toBe('-');
|
||||
@@ -506,7 +506,7 @@ describe('API Monitoring Utils', () => {
|
||||
|
||||
// Assert
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toEqual([]);
|
||||
expect(result).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('should handle undefined input', () => {
|
||||
@@ -518,7 +518,7 @@ describe('API Monitoring Utils', () => {
|
||||
|
||||
// Assert
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toEqual([]);
|
||||
expect(result).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('should handle mixed status code formats and preserve order', () => {
|
||||
@@ -555,7 +555,7 @@ describe('API Monitoring Utils', () => {
|
||||
|
||||
// Assert
|
||||
expect(result).toBeDefined();
|
||||
expect(result.length).toBe(3);
|
||||
expect(result).toHaveLength(3);
|
||||
|
||||
// Check order preservation - should maintain the same order as input
|
||||
expect(result[0].statusCode).toBe('404');
|
||||
@@ -675,7 +675,7 @@ describe('API Monitoring Utils', () => {
|
||||
|
||||
// Assert
|
||||
expect(result).toBeDefined();
|
||||
expect(result.data.result).toEqual([]);
|
||||
expect(result.data.result).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('should handle empty result array', () => {
|
||||
@@ -695,7 +695,7 @@ describe('API Monitoring Utils', () => {
|
||||
|
||||
// Assert
|
||||
expect(result).toBeDefined();
|
||||
expect(result.data.result).toEqual([]);
|
||||
expect(result.data.result).toStrictEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -779,7 +779,7 @@ describe('API Monitoring Utils', () => {
|
||||
|
||||
// Assert
|
||||
expect(result).toBeDefined();
|
||||
expect(result.length).toBe(2);
|
||||
expect(result).toHaveLength(2);
|
||||
|
||||
// Should have two filters, one for >= start code and one for <= end code
|
||||
const startRangeFilter = result.find((item) => item.op === '>=');
|
||||
@@ -811,7 +811,7 @@ describe('API Monitoring Utils', () => {
|
||||
|
||||
// Assert
|
||||
expect(result).toBeDefined();
|
||||
expect(result.length).toBe(2);
|
||||
expect(result).toHaveLength(2);
|
||||
|
||||
const startRangeFilter = result.find((item) => item.op === '>=');
|
||||
const endRangeFilter = result.find((item) => item.op === '<=');
|
||||
@@ -832,7 +832,7 @@ describe('API Monitoring Utils', () => {
|
||||
|
||||
// Assert
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toEqual([]);
|
||||
expect(result).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('should handle empty metric object', () => {
|
||||
@@ -841,7 +841,7 @@ describe('API Monitoring Utils', () => {
|
||||
|
||||
// Assert
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toEqual([]);
|
||||
expect(result).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('should handle metric without response_status_code', () => {
|
||||
@@ -855,7 +855,7 @@ describe('API Monitoring Utils', () => {
|
||||
|
||||
// Assert
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toEqual([]);
|
||||
expect(result).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('should handle unsupported status code range', () => {
|
||||
@@ -869,7 +869,7 @@ describe('API Monitoring Utils', () => {
|
||||
|
||||
// Assert
|
||||
expect(result).toBeDefined();
|
||||
expect(result.length).toBe(2);
|
||||
expect(result).toHaveLength(2);
|
||||
|
||||
// Should still have two filters
|
||||
const startRangeFilter = result.find((item) => item.op === '>=');
|
||||
|
||||
@@ -61,25 +61,29 @@ describe('AllEndpointsWidget - V5 Migration Validation', () => {
|
||||
// Query A: count()
|
||||
expect(queryA.aggregations).toBeDefined();
|
||||
expect(Array.isArray(queryA.aggregations)).toBe(true);
|
||||
expect(queryA.aggregations).toEqual([{ expression: 'count()' }]);
|
||||
expect(queryA.aggregations).toStrictEqual([{ expression: 'count()' }]);
|
||||
expect(queryA).not.toHaveProperty('aggregateAttribute');
|
||||
|
||||
// Query B: p99(duration_nano)
|
||||
expect(queryB.aggregations).toBeDefined();
|
||||
expect(Array.isArray(queryB.aggregations)).toBe(true);
|
||||
expect(queryB.aggregations).toEqual([{ expression: 'p99(duration_nano)' }]);
|
||||
expect(queryB.aggregations).toStrictEqual([
|
||||
{ expression: 'p99(duration_nano)' },
|
||||
]);
|
||||
expect(queryB).not.toHaveProperty('aggregateAttribute');
|
||||
|
||||
// Query C: max(timestamp)
|
||||
expect(queryC.aggregations).toBeDefined();
|
||||
expect(Array.isArray(queryC.aggregations)).toBe(true);
|
||||
expect(queryC.aggregations).toEqual([{ expression: 'max(timestamp)' }]);
|
||||
expect(queryC.aggregations).toStrictEqual([
|
||||
{ expression: 'max(timestamp)' },
|
||||
]);
|
||||
expect(queryC).not.toHaveProperty('aggregateAttribute');
|
||||
|
||||
// Query D: count() (disabled, for errors)
|
||||
expect(queryD.aggregations).toBeDefined();
|
||||
expect(Array.isArray(queryD.aggregations)).toBe(true);
|
||||
expect(queryD.aggregations).toEqual([{ expression: 'count()' }]);
|
||||
expect(queryD.aggregations).toStrictEqual([{ expression: 'count()' }]);
|
||||
expect(queryD).not.toHaveProperty('aggregateAttribute');
|
||||
});
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ describe('EndpointDropdown - V5 Migration Validation', () => {
|
||||
// V5 Aggregation format: aggregations array (not aggregateAttribute)
|
||||
expect(queryA.aggregations).toBeDefined();
|
||||
expect(Array.isArray(queryA.aggregations)).toBe(true);
|
||||
expect(queryA.aggregations?.[0]).toEqual({
|
||||
expect(queryA.aggregations?.[0]).toStrictEqual({
|
||||
expression: 'count()',
|
||||
});
|
||||
expect(queryA).not.toHaveProperty('aggregateAttribute');
|
||||
|
||||
@@ -19,7 +19,7 @@ describe('API Monitoring Query Params', () => {
|
||||
describe('getApiMonitoringParams', () => {
|
||||
it('returns default params when no query param exists', () => {
|
||||
const search = '';
|
||||
expect(getApiMonitoringParams(search)).toEqual(DEFAULT_PARAMS);
|
||||
expect(getApiMonitoringParams(search)).toStrictEqual(DEFAULT_PARAMS);
|
||||
});
|
||||
|
||||
it('parses URL query params correctly', () => {
|
||||
@@ -52,7 +52,7 @@ describe('API Monitoring Query Params', () => {
|
||||
urlParams.set('apiMonitoringParams', 'invalid-json');
|
||||
const search = `?${urlParams.toString()}`;
|
||||
|
||||
expect(getApiMonitoringParams(search)).toEqual(DEFAULT_PARAMS);
|
||||
expect(getApiMonitoringParams(search)).toStrictEqual(DEFAULT_PARAMS);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ window.ResizeObserver =
|
||||
describe('BillingContainer', () => {
|
||||
jest.setTimeout(30000);
|
||||
|
||||
test('Component should render', async () => {
|
||||
it('Component should render', async () => {
|
||||
render(<BillingContainer />);
|
||||
|
||||
const dataInjection = screen.getByRole('columnheader', {
|
||||
@@ -61,7 +61,7 @@ describe('BillingContainer', () => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
test('OnTrail', async () => {
|
||||
it('OnTrail', async () => {
|
||||
// Pin "now" so trial end (20 Oct 2023) is tomorrow => "1 days_remaining"
|
||||
|
||||
render(
|
||||
@@ -73,17 +73,19 @@ describe('BillingContainer', () => {
|
||||
// If the component schedules any setTimeout on mount, flush them:
|
||||
jest.runOnlyPendingTimers();
|
||||
|
||||
expect(await screen.findByText('Free Trial')).toBeInTheDocument();
|
||||
expect(await screen.findByText('billing')).toBeInTheDocument();
|
||||
expect(await screen.findByText(/\$0/i)).toBeInTheDocument();
|
||||
await expect(screen.findByText('Free Trial')).resolves.toBeInTheDocument();
|
||||
await expect(screen.findByText('billing')).resolves.toBeInTheDocument();
|
||||
await expect(screen.findByText(/\$0/i)).resolves.toBeInTheDocument();
|
||||
|
||||
expect(
|
||||
await screen.findByText(
|
||||
await expect(
|
||||
screen.findByText(
|
||||
/You are in free trial period. Your free trial will end on 20 Oct 2023/i,
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
).resolves.toBeInTheDocument();
|
||||
|
||||
expect(await screen.findByText(/1 days_remaining/i)).toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByText(/1 days_remaining/i),
|
||||
).resolves.toBeInTheDocument();
|
||||
|
||||
const upgradeButtons = await screen.findAllByRole('button', {
|
||||
name: /upgrade_plan/i,
|
||||
@@ -91,13 +93,15 @@ describe('BillingContainer', () => {
|
||||
expect(upgradeButtons).toHaveLength(2);
|
||||
expect(upgradeButtons[1]).toBeInTheDocument();
|
||||
|
||||
expect(await screen.findByText(/checkout_plans/i)).toBeInTheDocument();
|
||||
expect(
|
||||
await screen.findByRole('link', { name: /here/i }),
|
||||
).toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByText(/checkout_plans/i),
|
||||
).resolves.toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByRole('link', { name: /here/i }),
|
||||
).resolves.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('OnTrail but trialConvertedToSubscription', async () => {
|
||||
it('OnTrail but trialConvertedToSubscription', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<BillingContainer />,
|
||||
@@ -137,7 +141,7 @@ describe('BillingContainer', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('Not on ontrail', async () => {
|
||||
it('Not on ontrail', async () => {
|
||||
const { findByText } = render(
|
||||
<BillingContainer />,
|
||||
{},
|
||||
|
||||
@@ -242,7 +242,7 @@ describe('utils', () => {
|
||||
);
|
||||
|
||||
expect(rrulestr).toHaveBeenCalledWith(FREQ_DAILY);
|
||||
expect(result).toEqual([
|
||||
expect(result).toStrictEqual([
|
||||
new Date(MOCK_DATE_STRING),
|
||||
new Date('2024-01-16T10:30:00Z'),
|
||||
new Date('2024-01-17T10:30:00Z'),
|
||||
@@ -300,7 +300,7 @@ describe('utils', () => {
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result?.map((res) => formatDate(res))).toEqual([
|
||||
expect(result?.map((res) => formatDate(res))).toStrictEqual([
|
||||
'15-01-2024 10:30:00',
|
||||
'01-02-2024 10:30:00',
|
||||
'15-02-2024 10:30:00',
|
||||
@@ -319,7 +319,7 @@ describe('utils', () => {
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result?.map((res) => formatDate(res))).toEqual([
|
||||
expect(result?.map((res) => formatDate(res))).toStrictEqual([
|
||||
'15-01-2024 12:30:00',
|
||||
'19-01-2024 12:30:00',
|
||||
'22-01-2024 12:30:00',
|
||||
@@ -339,7 +339,7 @@ describe('utils', () => {
|
||||
expect(result).toBeDefined();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
// today included (15-01-2024 00:30:00)
|
||||
expect(result?.map((res) => formatDate(res))).toEqual([
|
||||
expect(result?.map((res) => formatDate(res))).toStrictEqual([
|
||||
'15-01-2024 10:30:00',
|
||||
'19-01-2024 10:30:00',
|
||||
'22-01-2024 10:30:00',
|
||||
@@ -359,7 +359,7 @@ describe('utils', () => {
|
||||
expect(result).toBeDefined();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
// today excluded (15-01-2024 00:30:00)
|
||||
expect(result?.map((res) => formatDate(res))).toEqual([
|
||||
expect(result?.map((res) => formatDate(res))).toStrictEqual([
|
||||
'19-01-2024 00:00:00',
|
||||
'22-01-2024 00:00:00',
|
||||
'26-01-2024 00:00:00',
|
||||
@@ -379,7 +379,7 @@ describe('utils', () => {
|
||||
expect(result).toBeDefined();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
// today excluded (15-01-2024 00:30:00)
|
||||
expect(result?.map((res) => formatDate(res))).toEqual([
|
||||
expect(result?.map((res) => formatDate(res))).toStrictEqual([
|
||||
'19-01-2024 00:30:00',
|
||||
'22-01-2024 00:30:00',
|
||||
'26-01-2024 00:30:00',
|
||||
@@ -398,7 +398,7 @@ describe('utils', () => {
|
||||
expect(result).toBeDefined();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
// today included (15-01-2024 10:30:00)
|
||||
expect(result?.map((res) => formatDate(res))).toEqual([
|
||||
expect(result?.map((res) => formatDate(res))).toStrictEqual([
|
||||
'15-01-2024 10:30:00',
|
||||
'15-02-2024 10:30:00',
|
||||
'15-03-2024 10:30:00',
|
||||
@@ -417,7 +417,7 @@ describe('utils', () => {
|
||||
expect(result).toBeDefined();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
// today excluded (15-01-2024 10:30:00)
|
||||
expect(result?.map((res) => formatDate(res))).toEqual([
|
||||
expect(result?.map((res) => formatDate(res))).toStrictEqual([
|
||||
'15-02-2024 00:00:00',
|
||||
'15-03-2024 00:00:00',
|
||||
'15-04-2024 00:00:00',
|
||||
@@ -436,7 +436,7 @@ describe('utils', () => {
|
||||
expect(result).toBeDefined();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
// today excluded (15-01-2024 10:30:00)
|
||||
expect(result?.map((res) => formatDate(res))).toEqual([
|
||||
expect(result?.map((res) => formatDate(res))).toStrictEqual([
|
||||
'15-02-2024 00:30:00',
|
||||
'15-03-2024 00:30:00',
|
||||
'15-04-2024 00:30:00',
|
||||
@@ -455,7 +455,7 @@ describe('utils', () => {
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result?.map((res) => formatDate(res))).toEqual([
|
||||
expect(result?.map((res) => formatDate(res))).toStrictEqual([
|
||||
'29-01-2024 10:30:00',
|
||||
'29-02-2024 10:30:00',
|
||||
'29-03-2024 10:30:00',
|
||||
@@ -474,7 +474,7 @@ describe('utils', () => {
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result?.map((res) => formatDate(res))).toEqual([
|
||||
expect(result?.map((res) => formatDate(res))).toStrictEqual([
|
||||
'31-01-2024 10:30:00',
|
||||
'31-03-2024 10:30:00',
|
||||
'31-05-2024 10:30:00',
|
||||
@@ -511,7 +511,7 @@ describe('utils', () => {
|
||||
5,
|
||||
);
|
||||
|
||||
expect(result?.map((res) => formatDate(res))).toEqual([
|
||||
expect(result?.map((res) => formatDate(res))).toStrictEqual([
|
||||
'29-01-2023 10:30:00',
|
||||
'29-03-2023 10:30:00',
|
||||
'29-04-2023 10:30:00',
|
||||
@@ -529,7 +529,7 @@ describe('utils', () => {
|
||||
);
|
||||
expect(result).toBeDefined();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result?.map((res) => formatDate(res))).toEqual([
|
||||
expect(result?.map((res) => formatDate(res))).toStrictEqual([
|
||||
'15-01-2024 10:40:00',
|
||||
'16-01-2024 10:40:00',
|
||||
'17-01-2024 10:40:00',
|
||||
@@ -547,7 +547,7 @@ describe('utils', () => {
|
||||
);
|
||||
expect(result).toBeDefined();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result?.map((res) => formatDate(res))).toEqual([
|
||||
expect(result?.map((res) => formatDate(res))).toStrictEqual([
|
||||
'16-01-2024 00:00:00',
|
||||
'17-01-2024 00:00:00',
|
||||
'18-01-2024 00:00:00',
|
||||
@@ -565,7 +565,7 @@ describe('utils', () => {
|
||||
);
|
||||
expect(result).toBeDefined();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result?.map((res) => formatDate(res))).toEqual([
|
||||
expect(result?.map((res) => formatDate(res))).toStrictEqual([
|
||||
'16-01-2024 00:30:00',
|
||||
'17-01-2024 00:30:00',
|
||||
'18-01-2024 00:30:00',
|
||||
@@ -583,7 +583,7 @@ describe('utils', () => {
|
||||
);
|
||||
expect(result).toBeDefined();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result?.map((res) => formatDate(res))).toEqual([
|
||||
expect(result?.map((res) => formatDate(res))).toStrictEqual([
|
||||
'15-01-2024 10:30:00',
|
||||
'16-01-2024 10:30:00',
|
||||
'17-01-2024 10:30:00',
|
||||
@@ -621,7 +621,7 @@ describe('utils', () => {
|
||||
);
|
||||
expect(result).toBeDefined();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result?.map((res) => formatDate(res))).toEqual([
|
||||
expect(result?.map((res) => formatDate(res))).toStrictEqual([
|
||||
'31-01-2024 10:30:00',
|
||||
'01-02-2024 10:30:00',
|
||||
'02-02-2024 10:30:00',
|
||||
|
||||
@@ -333,7 +333,7 @@ describe('QuerySection', () => {
|
||||
|
||||
const result = mockUseQueryBuilder.redirectWithQueryBuilderData.mock.calls[0];
|
||||
|
||||
expect(result[0]).toEqual({
|
||||
expect(result[0]).toStrictEqual({
|
||||
id: MOCK_UUID,
|
||||
queryType: EQueryType.QUERY_BUILDER,
|
||||
unit: undefined,
|
||||
@@ -351,7 +351,7 @@ describe('QuerySection', () => {
|
||||
clickhouse_sql: [initialClickHouseData],
|
||||
});
|
||||
|
||||
expect(result[1]).toEqual({
|
||||
expect(result[1]).toStrictEqual({
|
||||
[QueryParams.alertType]: AlertTypes.METRICS_BASED_ALERT,
|
||||
[QueryParams.ruleType]: AlertDetectionTypes.THRESHOLD_ALERT,
|
||||
});
|
||||
@@ -371,7 +371,7 @@ describe('QuerySection', () => {
|
||||
const [queryArg] =
|
||||
mockUseQueryBuilder.redirectWithQueryBuilderData.mock.calls[0];
|
||||
|
||||
expect(queryArg).toEqual({
|
||||
expect(queryArg).toStrictEqual({
|
||||
...mockUseQueryBuilder.currentQuery,
|
||||
queryType: EQueryType.PROM,
|
||||
});
|
||||
@@ -425,7 +425,7 @@ describe('QuerySection', () => {
|
||||
const [queryArg] =
|
||||
mockUseQueryBuilder.redirectWithQueryBuilderData.mock.calls[0];
|
||||
|
||||
expect(queryArg).toEqual({
|
||||
expect(queryArg).toStrictEqual({
|
||||
...mockCurrentQueryWithPromQL,
|
||||
queryType: EQueryType.QUERY_BUILDER,
|
||||
});
|
||||
@@ -479,7 +479,7 @@ describe('QuerySection', () => {
|
||||
const [queryArg] =
|
||||
mockUseQueryBuilder.redirectWithQueryBuilderData.mock.calls[0];
|
||||
|
||||
expect(queryArg).toEqual({
|
||||
expect(queryArg).toStrictEqual({
|
||||
...mockCurrentQueryWithClickhouseSQL,
|
||||
queryType: EQueryType.QUERY_BUILDER,
|
||||
});
|
||||
|
||||
@@ -54,7 +54,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_ALERT_NAME',
|
||||
payload: 'Test Alert',
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_ALERT_STATE,
|
||||
name: 'Test Alert',
|
||||
});
|
||||
@@ -66,7 +66,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_ALERT_LABELS',
|
||||
payload: labels,
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_ALERT_STATE,
|
||||
labels,
|
||||
});
|
||||
@@ -77,7 +77,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_Y_AXIS_UNIT',
|
||||
payload: 'ms',
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_ALERT_STATE,
|
||||
yAxisUnit: 'ms',
|
||||
});
|
||||
@@ -90,7 +90,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
yAxisUnit: 'ms',
|
||||
};
|
||||
const result = alertCreationReducer(modifiedState, { type: 'RESET' });
|
||||
expect(result).toEqual(INITIAL_ALERT_STATE);
|
||||
expect(result).toStrictEqual(INITIAL_ALERT_STATE);
|
||||
});
|
||||
|
||||
it(TEST_SET_INITIAL_STATE_FROM_PAYLOAD, () => {
|
||||
@@ -103,7 +103,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_INITIAL_STATE',
|
||||
payload: newState,
|
||||
});
|
||||
expect(result).toEqual(newState);
|
||||
expect(result).toStrictEqual(newState);
|
||||
});
|
||||
|
||||
it(TEST_RETURN_STATE_FOR_UNKNOWN_ACTION, () => {
|
||||
@@ -112,7 +112,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
|
||||
{ type: UNKNOWN_ACTION_TYPE } as any,
|
||||
);
|
||||
expect(result).toEqual(INITIAL_ALERT_STATE);
|
||||
expect(result).toStrictEqual(INITIAL_ALERT_STATE);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -211,7 +211,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_SELECTED_QUERY',
|
||||
payload: 'B',
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_ALERT_THRESHOLD_STATE,
|
||||
selectedQuery: 'B',
|
||||
});
|
||||
@@ -222,7 +222,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_OPERATOR',
|
||||
payload: AlertThresholdOperator.IS_BELOW,
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_ALERT_THRESHOLD_STATE,
|
||||
operator: AlertThresholdOperator.IS_BELOW,
|
||||
});
|
||||
@@ -233,7 +233,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_MATCH_TYPE',
|
||||
payload: AlertThresholdMatchType.ALL_THE_TIME,
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_ALERT_THRESHOLD_STATE,
|
||||
matchType: AlertThresholdMatchType.ALL_THE_TIME,
|
||||
});
|
||||
@@ -255,7 +255,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_THRESHOLDS',
|
||||
payload: newThresholds,
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_ALERT_THRESHOLD_STATE,
|
||||
thresholds: newThresholds,
|
||||
});
|
||||
@@ -272,7 +272,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
thresholds: [],
|
||||
};
|
||||
const result = alertThresholdReducer(modifiedState, { type: 'RESET' });
|
||||
expect(result).toEqual(INITIAL_ALERT_THRESHOLD_STATE);
|
||||
expect(result).toStrictEqual(INITIAL_ALERT_THRESHOLD_STATE);
|
||||
});
|
||||
|
||||
it(TEST_SET_INITIAL_STATE_FROM_PAYLOAD, () => {
|
||||
@@ -289,7 +289,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_INITIAL_STATE',
|
||||
payload: newState,
|
||||
});
|
||||
expect(result).toEqual(newState);
|
||||
expect(result).toStrictEqual(newState);
|
||||
});
|
||||
|
||||
it(TEST_RETURN_STATE_FOR_UNKNOWN_ACTION, () => {
|
||||
@@ -298,7 +298,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
|
||||
{ type: UNKNOWN_ACTION_TYPE } as any,
|
||||
);
|
||||
expect(result).toEqual(INITIAL_ALERT_THRESHOLD_STATE);
|
||||
expect(result).toStrictEqual(INITIAL_ALERT_THRESHOLD_STATE);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -308,7 +308,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_SEND_NOTIFICATION_IF_DATA_IS_MISSING',
|
||||
payload: { toleranceLimit: 21, timeUnit: UniversalYAxisUnit.HOURS },
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_ADVANCED_OPTIONS_STATE,
|
||||
sendNotificationIfDataIsMissing: {
|
||||
...INITIAL_ADVANCED_OPTIONS_STATE.sendNotificationIfDataIsMissing,
|
||||
@@ -323,7 +323,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'TOGGLE_SEND_NOTIFICATION_IF_DATA_IS_MISSING',
|
||||
payload: true,
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_ADVANCED_OPTIONS_STATE,
|
||||
sendNotificationIfDataIsMissing: {
|
||||
...INITIAL_ADVANCED_OPTIONS_STATE.sendNotificationIfDataIsMissing,
|
||||
@@ -337,7 +337,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_ENFORCE_MINIMUM_DATAPOINTS',
|
||||
payload: { minimumDatapoints: 10 },
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_ADVANCED_OPTIONS_STATE,
|
||||
enforceMinimumDatapoints: {
|
||||
...INITIAL_ADVANCED_OPTIONS_STATE.enforceMinimumDatapoints,
|
||||
@@ -351,7 +351,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'TOGGLE_ENFORCE_MINIMUM_DATAPOINTS',
|
||||
payload: true,
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_ADVANCED_OPTIONS_STATE,
|
||||
enforceMinimumDatapoints: {
|
||||
...INITIAL_ADVANCED_OPTIONS_STATE.enforceMinimumDatapoints,
|
||||
@@ -365,7 +365,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_DELAY_EVALUATION',
|
||||
payload: { delay: 10, timeUnit: UniversalYAxisUnit.HOURS },
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_ADVANCED_OPTIONS_STATE,
|
||||
delayEvaluation: { delay: 10, timeUnit: UniversalYAxisUnit.HOURS },
|
||||
});
|
||||
@@ -386,7 +386,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_EVALUATION_CADENCE',
|
||||
payload: newCadence,
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_ADVANCED_OPTIONS_STATE,
|
||||
evaluationCadence: {
|
||||
...INITIAL_ADVANCED_OPTIONS_STATE.evaluationCadence,
|
||||
@@ -400,7 +400,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_EVALUATION_CADENCE_MODE',
|
||||
payload: 'custom',
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_ADVANCED_OPTIONS_STATE,
|
||||
evaluationCadence: {
|
||||
...INITIAL_ADVANCED_OPTIONS_STATE.evaluationCadence,
|
||||
@@ -415,7 +415,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
delayEvaluation: { delay: 10, timeUnit: UniversalYAxisUnit.HOURS },
|
||||
};
|
||||
const result = advancedOptionsReducer(modifiedState, { type: 'RESET' });
|
||||
expect(result).toEqual(INITIAL_ADVANCED_OPTIONS_STATE);
|
||||
expect(result).toStrictEqual(INITIAL_ADVANCED_OPTIONS_STATE);
|
||||
});
|
||||
|
||||
it(TEST_SET_INITIAL_STATE_FROM_PAYLOAD, () => {
|
||||
@@ -431,7 +431,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_INITIAL_STATE',
|
||||
payload: newState,
|
||||
});
|
||||
expect(result).toEqual(newState);
|
||||
expect(result).toStrictEqual(newState);
|
||||
});
|
||||
|
||||
it(TEST_RETURN_STATE_FOR_UNKNOWN_ACTION, () => {
|
||||
@@ -440,7 +440,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
|
||||
{ type: UNKNOWN_ACTION_TYPE } as any,
|
||||
);
|
||||
expect(result).toEqual(INITIAL_ADVANCED_OPTIONS_STATE);
|
||||
expect(result).toStrictEqual(INITIAL_ADVANCED_OPTIONS_STATE);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -455,7 +455,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_WINDOW_TYPE',
|
||||
payload: 'rolling',
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
windowType: 'rolling',
|
||||
timeframe: INITIAL_EVALUATION_WINDOW_STATE.timeframe,
|
||||
startingAt: INITIAL_EVALUATION_WINDOW_STATE.startingAt,
|
||||
@@ -467,7 +467,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_WINDOW_TYPE',
|
||||
payload: 'cumulative',
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
windowType: 'cumulative',
|
||||
timeframe: 'currentHour',
|
||||
startingAt: INITIAL_EVALUATION_WINDOW_STATE.startingAt,
|
||||
@@ -479,7 +479,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_TIMEFRAME',
|
||||
payload: '10m0s',
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_EVALUATION_WINDOW_STATE,
|
||||
timeframe: '10m0s',
|
||||
});
|
||||
@@ -496,7 +496,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_STARTING_AT',
|
||||
payload: newStartingAt,
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_EVALUATION_WINDOW_STATE,
|
||||
startingAt: newStartingAt,
|
||||
});
|
||||
@@ -514,7 +514,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
},
|
||||
};
|
||||
const result = evaluationWindowReducer(modifiedState, { type: 'RESET' });
|
||||
expect(result).toEqual(INITIAL_EVALUATION_WINDOW_STATE);
|
||||
expect(result).toStrictEqual(INITIAL_EVALUATION_WINDOW_STATE);
|
||||
});
|
||||
|
||||
it(TEST_SET_INITIAL_STATE_FROM_PAYLOAD, () => {
|
||||
@@ -532,7 +532,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_INITIAL_STATE',
|
||||
payload: newState,
|
||||
});
|
||||
expect(result).toEqual(newState);
|
||||
expect(result).toStrictEqual(newState);
|
||||
});
|
||||
|
||||
it(TEST_RETURN_STATE_FOR_UNKNOWN_ACTION, () => {
|
||||
@@ -541,7 +541,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
|
||||
{ type: UNKNOWN_ACTION_TYPE } as any,
|
||||
);
|
||||
expect(result).toEqual(INITIAL_EVALUATION_WINDOW_STATE);
|
||||
expect(result).toStrictEqual(INITIAL_EVALUATION_WINDOW_STATE);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -555,7 +555,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
payload: notifications,
|
||||
},
|
||||
);
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_NOTIFICATION_SETTINGS_STATE,
|
||||
multipleNotifications: notifications,
|
||||
});
|
||||
@@ -570,7 +570,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
type: 'SET_MULTIPLE_NOTIFICATIONS',
|
||||
payload: null,
|
||||
});
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...modifiedState,
|
||||
multipleNotifications: null,
|
||||
});
|
||||
@@ -590,7 +590,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
payload: reNotification,
|
||||
},
|
||||
);
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_NOTIFICATION_SETTINGS_STATE,
|
||||
reNotification,
|
||||
});
|
||||
@@ -605,7 +605,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
payload: description,
|
||||
},
|
||||
);
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_NOTIFICATION_SETTINGS_STATE,
|
||||
description,
|
||||
});
|
||||
@@ -619,7 +619,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
payload: true,
|
||||
},
|
||||
);
|
||||
expect(result).toEqual({
|
||||
expect(result).toStrictEqual({
|
||||
...INITIAL_NOTIFICATION_SETTINGS_STATE,
|
||||
routingPolicies: true,
|
||||
});
|
||||
@@ -640,7 +640,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
const result = notificationSettingsReducer(modifiedState, {
|
||||
type: 'RESET',
|
||||
});
|
||||
expect(result).toEqual(INITIAL_NOTIFICATION_SETTINGS_STATE);
|
||||
expect(result).toStrictEqual(INITIAL_NOTIFICATION_SETTINGS_STATE);
|
||||
});
|
||||
|
||||
it(TEST_SET_INITIAL_STATE_FROM_PAYLOAD, () => {
|
||||
@@ -662,7 +662,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
payload: newState,
|
||||
},
|
||||
);
|
||||
expect(result).toEqual(newState);
|
||||
expect(result).toStrictEqual(newState);
|
||||
});
|
||||
|
||||
it(TEST_RETURN_STATE_FOR_UNKNOWN_ACTION, () => {
|
||||
@@ -671,7 +671,7 @@ describe('CreateAlertV2 Context Utils', () => {
|
||||
|
||||
{ type: UNKNOWN_ACTION_TYPE } as any,
|
||||
);
|
||||
expect(result).toEqual(INITIAL_NOTIFICATION_SETTINGS_STATE);
|
||||
expect(result).toStrictEqual(INITIAL_NOTIFICATION_SETTINGS_STATE);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user