Compare commits

..

14 Commits

Author SHA1 Message Date
Jatinderjit Singh
87bf9257b4 rename buildReceiverStage -> createReceiverStage 2026-04-28 17:51:32 +05:30
Jatinderjit Singh
2d7e91c669 refactor: remove dead orgID param from task constructors
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 17:27:54 +05:30
Jatinderjit Singh
12d487b91c refactor: pass MaintenanceMuter directly to pipelineBuilder
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 16:53:43 +05:30
Jatinderjit Singh
c7bee0b6d3 chore: replace SPDX tag with full Apache 2.0 license boilerplate
The full license text is unambiguously compliant with Apache 2.0 Section 4(a),
which requires giving recipients "a copy of this License".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 16:53:43 +05:30
Jatinderjit Singh
545de41c10 chore: add license header to pipeline_builder.go
Copied code originates from Apache-2.0 licensed Prometheus Alertmanager;
add dual copyright + SPDX identifier following the repo's convention.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 16:53:43 +05:30
Jatinderjit Singh
5c2a355030 refactor: move maintenance mute stage into custom pipelineBuilder
Copy notify.PipelineBuilder locally so we can inject mms between the
silence stage and the receiver stage (GossipSettle → Inhibit →
TimeActive → TimeMute → Silence → mms → Receiver), matching the
correct suppression order the team requires.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 16:53:43 +05:30
Jatinderjit Singh
fa9ad41a1b refactor: wrap routing pipeline once instead of per-route injection
Replace the per-route-entry loop with a single MultiStage wrap so
maintenance suppression runs once per dispatch group before routing.
2026-04-28 16:53:43 +05:30
Jatinderjit Singh
a8790c6fe9 add maintenanceMuteStage to move planned maintenance to alertmanager
Rules previously skipped rule.Eval() entirely during maintenance windows.
This change moves suppression to MaintenanceMuter, injected as a Stage
in the alertmanager notification pipeline. Now rules always evaluate and
everys suppression is handled by alertmanager.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 16:53:43 +05:30
Jatinderjit Singh
d0e748ed37 fix: maintenance ignores recurrence when fixed times also set 2026-04-28 16:53:43 +05:30
Nikhil Mantri
ffd493617f feat(infra-monitoring): v2 pods list API (#10833)
* chore: baseline setup

* chore: endpoint detail update

* chore: added logic for hosts v3 api

* fix: bug fix

* chore: disk usage

* chore: added validate function

* chore: added some unit tests

* chore: return status as a string

* chore: yarn generate api

* chore: removed isSendingK8sAgentsMetricsCode

* chore: moved funcs

* chore: added validation on order by

* chore: added pods list logic

* chore: updated openapi yml

* chore: updated spec

* chore: pods api meta start time

* chore: nil pointer check

* chore: nil pointer dereference fix in req.Filter

* chore: added temporalities of metrics

* chore: added pods metrics temporality

* chore: unified composite key function

* chore: code improvements

* chore: added pods list api updates

* chore: hostStatusNone added for clarity that this field can be left empty as well in payload

* chore: yarn generate api

* chore: return errors from getMetadata and lint fix

* chore: return errors from getMetadata and lint fix

* chore: added hostName logic

* chore: modified getMetadata query

* chore: add type for response and files rearrange

* chore: warnings added passing from queryResponse warning to host lists response struct

* chore: added better metrics existence check

* chore: added a TODO remark

* chore: added required metrics check

* chore: distributed samples table to local table change for get metadata

* chore: frontend fix

* chore: endpoint correction

* chore: endpoint modification openapi

* chore: escape backtick to prevent sql injection

* chore: rearrage

* chore: improvements

* chore: validate order by to validate function

* chore: improved description

* chore: added TODOs and made filterByStatus a part of filter struct

* chore: ignore empty string hosts in get active hosts

* feat(infra-monitoring): v2 hosts list - return counts of active & inactive hosts for custom group by attributes (#10956)

* chore: add functionality for showing active and inactive counts in custom group by

* chore: bug fix

* chore: added subquery for active and total count

* chore: ignore empty string hosts in get active hosts

* fix: sinceUnixMilli for determining active hosts compute once per request

* chore: refactor code

* chore: rename HostsList -> ListHosts

* chore: rearrangement

* chore: inframonitoring types renaming

* chore: added types package

* chore: file structure further breakdown for clarity

* chore: comments correction

* chore: removed temporalities

* chore: pods code restructuring

* chore: comments resolve

* chore: added json tag required: true

* chore: removed pod metric temporalities

* chore: removed internal server error

* chore: added status unauthorized

* chore: remove a defensive nil map check, the function ensure non-nil map when err nil

* chore: cleanup and rename

* chore: make sort stable in case of tiebreaker by comparing composite group by keys

* chore: regen api client for inframonitoring

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore: added required tags

* chore: added support for pod phase unknown

* chore: removed pods - order by phase

* chore: improved api description to document -1 as no data in numeric fields

* fix: rebase fixes

* feat(infra-monitoring): v2 pods list apis - phase counts when custom grouping (#11088)

* chore: added phase counts feature

* chore: added queries for pod phase counts in custom group by

* chore: added unknown phase count

* fix: isPodUIDInGroupBy in buildPodRecords

* chore: 3 cte --> 2 cte

* chore: pod phase with local table of time series as counts

* chore: comment correction

* chore: corrected comment

* chore: value column for samples table added

* chore: removed query G for phase counts

* chore: rename variable

* chore: added PodPhaseNum constants to types

* chore: updated comment

* chore: formatted file

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Ashwin Bhatkal <ashwin96@gmail.com>
2026-04-28 10:19:26 +00:00
Pandey
3f95d35ad5 chore: add @therealpandey with @srikanthcvv (#11126)
#### Temporary

- add @therealpandey with @srikanthcvv
2026-04-28 10:01:39 +00:00
Piyush Singariya
9e5678d6b3 CI: JSON QB E2E Integration Suite (#10863)
* feat: enable JSON Path index

* fix: contextual path index usage

* test: fix unit tests

* feat: align negative operators to include other logs

* fix: primitive conditions working

* fix: indexed tests passing

* fix: array type filtering from dynamic arrays

* fix: unit tests

* fix: remove not used paths from testdata

* fix: unit tests

* fix: comment

* fix: indexed unit tests

* fix: array json element comparison

* feat: change filtering of dynamic arrays

* fix: dynamic array tests

* fix: stringified integer value input

* fix: better review for test file

* fix: negative operator check

* ci: lint changes

* chore: import tests from older pr

* fix: better tests

* fix: logs.py

* fix: body tests ready

* fix: better validations

* fix: dynamically change insert stmt for body_v2 availability

* test: with higher migrator version

* fix: type ambiguity

* fix: test

* test: updated validation

* fix: tons of changes

* chore: remove redundent comparison

* ci: tests fixed

* fix: upgraded collector version

* fix: qbtoexpr tests

* fix: go sum

* chore: upgrade collector version v0.144.3-rc.4

* fix: tests

* ci: test fix

* revert: remove db binaries

* test: selectField tests added

* fix: added safeguards in plan generation

* fix: name changed to field_map

* chore: changes based on review

* fix: changes based on review

* fix: remove unused promoted fixture

* test: integration test fix attempt 1

* fix: json access plan remval of AvailableTypes

* fix: invalid index usage on terminal condition

* test: added indexed tests separately

* test: select order by tests added

* fix: update jsontypeexporter

* fix: branches should tell missing array types

* fix: comment removed

* ci: test with updated collector

* fix: issue with FuzzyMatching and API failing

* test: select orderby works

* fix: int64 mapping

* fix: replacing JSONIndex with TelemetryFieldKeyIndex

* chore: update collector to stable release

* chore: update migrator version to stable release

* chore: error fix and unused code

* chore: go mod tidy

* chore: some changes in test to improve quality

* test: enhanced tests to work with backtick required key

* chore: comment removal

* fix: change based on review

* fix: change based on review

* fix: openapi ci

* ci: fix go tests

* fix: index needs body prefix

* fix: tests

* ci: polluted test fix

* fix: shift test files

* refactor(telemetrytypes): replace JSONDataTypeIndex with TelemetryFieldKeySkipIndex

* revert: mcp related changes

* feat: check query log as fixture

* fix: reuse querier fixtures

* chore: rename jsontypeexporter.py

* chore: py-fmt

* fix: minor fix

* fix: py-lint

* fix: changes based on review

* chore: fmt
2026-04-28 08:49:44 +00:00
Abhi kumar
941016f12c Feat/crosshair series highlight (#11013)
* chore: added changes for crosshair sync for tooltip

* chore: minor cleanup

* chore: updated the core structure

* chore: updated the types

* chore: minor cleanup

* feat: added changes for sereis highlighting on crosshair sync

* chore: pr review fixes

* chore: handled other cases of groupby

* chore: minor changes

* feat: tooltip sync across panels (#11114)

* feat: added changes for syncing tooltip

* fix: fixed other tooltips closing when clicked on top of root tooltip

* fix: highlighting first series

* chore: removed y-axis sync for tooltip mode

* chore: minor fix

* chore: fmt fix
2026-04-28 06:52:51 +00:00
Vinicius Lourenço
500ce85ccb chore(oxlint): run fixes (#11123)
Some checks failed
build-staging / prepare (push) Has been cancelled
build-staging / js-build (push) Has been cancelled
build-staging / go-build (push) Has been cancelled
build-staging / staging (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
* chore(oxlint): run fixes

* test(to-strict): failing due to missing props
2026-04-28 04:27:45 +00:00
267 changed files with 6333 additions and 2563 deletions

56
.github/CODEOWNERS vendored
View File

@@ -52,49 +52,49 @@ go.mod @therealpandey
# Querier Owners
/pkg/querier/ @srikanthccv
/pkg/variables/ @srikanthccv
/pkg/types/querybuildertypes/ @srikanthccv
/pkg/types/telemetrytypes/ @srikanthccv
/pkg/querybuilder/ @srikanthccv
/pkg/telemetrylogs/ @srikanthccv
/pkg/telemetrymetadata/ @srikanthccv
/pkg/telemetrymetrics/ @srikanthccv
/pkg/telemetrytraces/ @srikanthccv
/pkg/querier/ @srikanthccv @therealpandey
/pkg/variables/ @srikanthccv @therealpandey
/pkg/types/querybuildertypes/ @srikanthccv @therealpandey
/pkg/types/telemetrytypes/ @srikanthccv @therealpandey
/pkg/querybuilder/ @srikanthccv @therealpandey
/pkg/telemetrylogs/ @srikanthccv @therealpandey
/pkg/telemetrymetadata/ @srikanthccv @therealpandey
/pkg/telemetrymetrics/ @srikanthccv @therealpandey
/pkg/telemetrytraces/ @srikanthccv @therealpandey
# Metrics
/pkg/types/metrictypes/ @srikanthccv
/pkg/types/metricsexplorertypes/ @srikanthccv
/pkg/modules/metricsexplorer/ @srikanthccv
/pkg/prometheus/ @srikanthccv
/pkg/types/metrictypes/ @srikanthccv @therealpandey
/pkg/types/metricsexplorertypes/ @srikanthccv @therealpandey
/pkg/modules/metricsexplorer/ @srikanthccv @therealpandey
/pkg/prometheus/ @srikanthccv @therealpandey
# APM
/pkg/types/servicetypes/ @srikanthccv
/pkg/types/apdextypes/ @srikanthccv
/pkg/modules/apdex/ @srikanthccv
/pkg/modules/services/ @srikanthccv
/pkg/types/servicetypes/ @srikanthccv @therealpandey
/pkg/types/apdextypes/ @srikanthccv @therealpandey
/pkg/modules/apdex/ @srikanthccv @therealpandey
/pkg/modules/services/ @srikanthccv @therealpandey
# Dashboard
/pkg/types/dashboardtypes/ @srikanthccv
/pkg/modules/dashboard/ @srikanthccv
/pkg/types/dashboardtypes/ @srikanthccv @therealpandey
/pkg/modules/dashboard/ @srikanthccv @therealpandey
# Rule/Alertmanager
/pkg/types/ruletypes/ @srikanthccv
/pkg/types/alertmanagertypes @srikanthccv
/pkg/alertmanager/ @srikanthccv
/pkg/ruler/ @srikanthccv
/pkg/modules/rulestatehistory/ @srikanthccv
/pkg/types/rulestatehistorytypes/ @srikanthccv
/pkg/types/ruletypes/ @srikanthccv @therealpandey
/pkg/types/alertmanagertypes @srikanthccv @therealpandey
/pkg/alertmanager/ @srikanthccv @therealpandey
/pkg/ruler/ @srikanthccv @therealpandey
/pkg/modules/rulestatehistory/ @srikanthccv @therealpandey
/pkg/types/rulestatehistorytypes/ @srikanthccv @therealpandey
# Correlation-adjacent
/pkg/contextlinks/ @srikanthccv
/pkg/types/parsertypes/ @srikanthccv
/pkg/queryparser/ @srikanthccv
/pkg/contextlinks/ @srikanthccv @therealpandey
/pkg/types/parsertypes/ @srikanthccv @therealpandey
/pkg/queryparser/ @srikanthccv @therealpandey
# AuthN / AuthZ Owners

View File

@@ -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: |

View File

@@ -2474,6 +2474,97 @@ components:
- requiredMetricsCheck
- endTimeBeforeRetention
type: object
InframonitoringtypesPodPhase:
enum:
- pending
- running
- succeeded
- failed
- unknown
- ""
type: string
InframonitoringtypesPodRecord:
properties:
failedPodCount:
type: integer
meta:
additionalProperties: {}
nullable: true
type: object
pendingPodCount:
type: integer
podAge:
format: int64
type: integer
podCPU:
format: double
type: number
podCPULimit:
format: double
type: number
podCPURequest:
format: double
type: number
podMemory:
format: double
type: number
podMemoryLimit:
format: double
type: number
podMemoryRequest:
format: double
type: number
podPhase:
$ref: '#/components/schemas/InframonitoringtypesPodPhase'
podUID:
type: string
runningPodCount:
type: integer
succeededPodCount:
type: integer
unknownPodCount:
type: integer
required:
- podUID
- podCPU
- podCPURequest
- podCPULimit
- podMemory
- podMemoryRequest
- podMemoryLimit
- podPhase
- pendingPodCount
- runningPodCount
- succeededPodCount
- failedPodCount
- unknownPodCount
- podAge
- meta
type: object
InframonitoringtypesPods:
properties:
endTimeBeforeRetention:
type: boolean
records:
items:
$ref: '#/components/schemas/InframonitoringtypesPodRecord'
nullable: true
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
total:
type: integer
type:
$ref: '#/components/schemas/InframonitoringtypesResponseType'
warning:
$ref: '#/components/schemas/Querybuildertypesv5QueryWarnData'
required:
- type
- records
- total
- requiredMetricsCheck
- endTimeBeforeRetention
type: object
InframonitoringtypesPostableHosts:
properties:
end:
@@ -2500,6 +2591,32 @@ components:
- end
- limit
type: object
InframonitoringtypesPostablePods:
properties:
end:
format: int64
type: integer
filter:
$ref: '#/components/schemas/Querybuildertypesv5Filter'
groupBy:
items:
$ref: '#/components/schemas/Querybuildertypesv5GroupByKey'
nullable: true
type: array
limit:
type: integer
offset:
type: integer
orderBy:
$ref: '#/components/schemas/Querybuildertypesv5OrderBy'
start:
format: int64
type: integer
required:
- start
- end
- limit
type: object
InframonitoringtypesRequiredMetricsCheck:
properties:
missingMetrics:
@@ -4500,7 +4617,6 @@ components:
enum:
- attribute
- resource
nullable: true
type: string
SpantypesGettableSpanMapperGroups:
properties:
@@ -4528,6 +4644,8 @@ components:
type: object
SpantypesPostableSpanMapperGroup:
properties:
category:
$ref: '#/components/schemas/SpantypesSpanMapperGroupCategory'
condition:
$ref: '#/components/schemas/SpantypesSpanMapperGroupCondition'
enabled:
@@ -4536,6 +4654,7 @@ components:
type: string
required:
- name
- category
- condition
type: object
SpantypesSpanMapper:
@@ -4571,7 +4690,6 @@ components:
- enabled
type: object
SpantypesSpanMapperConfig:
nullable: true
properties:
sources:
items:
@@ -4583,6 +4701,8 @@ components:
type: object
SpantypesSpanMapperGroup:
properties:
category:
$ref: '#/components/schemas/SpantypesSpanMapperGroupCategory'
condition:
$ref: '#/components/schemas/SpantypesSpanMapperGroupCondition'
createdAt:
@@ -4607,11 +4727,13 @@ components:
- id
- orgId
- name
- category
- condition
- enabled
type: object
SpantypesSpanMapperGroupCategory:
type: object
SpantypesSpanMapperGroupCondition:
nullable: true
properties:
attributes:
items:
@@ -9418,6 +9540,12 @@ paths:
org.
operationId: ListSpanMapperGroups
parameters:
- explode: true
in: query
name: category
schema:
$ref: '#/components/schemas/SpantypesSpanMapperGroupCategory'
style: deepObject
- in: query
name: enabled
schema:
@@ -10875,7 +11003,9 @@ paths:
five metrics, and pagination via offset/limit. The response type is ''list''
for the default host.name grouping or ''grouped_list'' for custom groupBy
keys. Also reports missing required metrics and whether the requested time
range falls before the data retention boundary.'
range falls before the data retention boundary. Numeric metric fields (cpu,
memory, wait, load15, diskUsage) return -1 as a sentinel when no data is available
for that field.'
operationId: ListHosts
requestBody:
content:
@@ -10929,6 +11059,79 @@ paths:
summary: List Hosts for Infra Monitoring
tags:
- inframonitoring
/api/v2/infra_monitoring/pods:
post:
deprecated: false
description: 'Returns a paginated list of Kubernetes pods with key metrics:
CPU usage, CPU request/limit utilization, memory working set, memory request/limit
utilization, current pod phase (pending/running/succeeded/failed/unknown),
and pod age (ms since start time). Each pod includes metadata attributes (namespace,
node, workload owner such as deployment/statefulset/daemonset/job/cronjob,
cluster). Supports filtering via a filter expression, custom groupBy to aggregate
pods by any attribute, ordering by any of the six metrics (cpu, cpu_request,
cpu_limit, memory, memory_request, memory_limit), and pagination via offset/limit.
The response type is ''list'' for the default k8s.pod.uid grouping (each row
is one pod with its current phase) or ''grouped_list'' for custom groupBy
keys (each row aggregates pods in the group with per-phase counts: pendingPodCount,
runningPodCount, succeededPodCount, failedPodCount, unknownPodCount derived
from each pod''s latest phase in the window). Also reports missing required
metrics and whether the requested time range falls before the data retention
boundary. Numeric metric fields (podCPU, podCPURequest, podCPULimit, podMemory,
podMemoryRequest, podMemoryLimit, podAge) return -1 as a sentinel when no
data is available for that field.'
operationId: ListPods
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/InframonitoringtypesPostablePods'
responses:
"200":
content:
application/json:
schema:
properties:
data:
$ref: '#/components/schemas/InframonitoringtypesPods'
status:
type: string
required:
- status
- data
type: object
description: OK
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/RenderErrorResponse'
description: Bad Request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/RenderErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/RenderErrorResponse'
description: Forbidden
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/RenderErrorResponse'
description: Internal Server Error
security:
- api_key:
- VIEWER
- tokenizer:
- VIEWER
summary: List Pods for Infra Monitoring
tags:
- inframonitoring
/api/v2/livez:
get:
deprecated: false

View File

@@ -13,7 +13,6 @@ import (
"github.com/SigNoz/signoz/pkg/errors"
baserules "github.com/SigNoz/signoz/pkg/query-service/rules"
"github.com/SigNoz/signoz/pkg/types/ruletypes"
"github.com/SigNoz/signoz/pkg/valuer"
)
func PrepareTaskFunc(opts baserules.PrepareTaskOptions) (baserules.Task, error) {
@@ -49,7 +48,7 @@ func PrepareTaskFunc(opts baserules.PrepareTaskOptions) (baserules.Task, error)
rules = append(rules, tr)
// create ch rule task for evaluation
task = newTask(baserules.TaskTypeCh, opts.TaskName, evaluation.GetFrequency().Duration(), rules, opts.ManagerOpts, opts.NotifyFunc, opts.MaintenanceStore, opts.OrgID)
task = newTask(baserules.TaskTypeCh, opts.TaskName, evaluation.GetFrequency().Duration(), rules, opts.ManagerOpts, opts.NotifyFunc)
} else if opts.Rule.RuleType == ruletypes.RuleTypeProm {
@@ -73,7 +72,7 @@ func PrepareTaskFunc(opts baserules.PrepareTaskOptions) (baserules.Task, error)
rules = append(rules, pr)
// create promql rule task for evaluation
task = newTask(baserules.TaskTypeProm, opts.TaskName, evaluation.GetFrequency().Duration(), rules, opts.ManagerOpts, opts.NotifyFunc, opts.MaintenanceStore, opts.OrgID)
task = newTask(baserules.TaskTypeProm, opts.TaskName, evaluation.GetFrequency().Duration(), rules, opts.ManagerOpts, opts.NotifyFunc)
} else if opts.Rule.RuleType == ruletypes.RuleTypeAnomaly {
// create anomaly rule
@@ -96,7 +95,7 @@ func PrepareTaskFunc(opts baserules.PrepareTaskOptions) (baserules.Task, error)
rules = append(rules, ar)
// create anomaly rule task for evaluation
task = newTask(baserules.TaskTypeCh, opts.TaskName, evaluation.GetFrequency().Duration(), rules, opts.ManagerOpts, opts.NotifyFunc, opts.MaintenanceStore, opts.OrgID)
task = newTask(baserules.TaskTypeCh, opts.TaskName, evaluation.GetFrequency().Duration(), rules, opts.ManagerOpts, opts.NotifyFunc)
} else {
return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "unsupported rule type %s. Supported types: %s, %s", opts.Rule.RuleType, ruletypes.RuleTypeProm, ruletypes.RuleTypeThreshold)
@@ -210,9 +209,9 @@ func TestNotification(opts baserules.PrepareTestRuleOptions) (int, error) {
}
// newTask returns an appropriate group for the rule type
func newTask(taskType baserules.TaskType, name string, frequency time.Duration, rules []baserules.Rule, opts *baserules.ManagerOptions, notify baserules.NotifyFunc, maintenanceStore ruletypes.MaintenanceStore, orgID valuer.UUID) baserules.Task {
func newTask(taskType baserules.TaskType, name string, frequency time.Duration, rules []baserules.Rule, opts *baserules.ManagerOptions, notify baserules.NotifyFunc) baserules.Task {
if taskType == baserules.TaskTypeCh {
return baserules.NewRuleTask(name, "", frequency, rules, opts, notify, maintenanceStore, orgID)
return baserules.NewRuleTask(name, "", frequency, rules, opts, notify)
}
return baserules.NewPromRuleTask(name, "", frequency, rules, opts, notify, maintenanceStore, orgID)
return baserules.NewPromRuleTask(name, "", frequency, rules, opts, notify)
}

View File

@@ -212,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",
@@ -238,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": {

View File

@@ -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,
});

View File

@@ -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),

View File

@@ -13,7 +13,9 @@ import type {
import type {
InframonitoringtypesPostableHostsDTO,
InframonitoringtypesPostablePodsDTO,
ListHosts200,
ListPods200,
RenderErrorResponseDTO,
} from '../sigNoz.schemas';
@@ -21,7 +23,7 @@ import { GeneratedAPIInstance } from '../../../generatedAPIInstance';
import type { ErrorType, BodyType } from '../../../generatedAPIInstance';
/**
* Returns a paginated list of hosts with key infrastructure metrics: CPU usage (%), memory usage (%), I/O wait (%), disk usage (%), and 15-minute load average. Each host includes its current status (active/inactive based on metrics reported in the last 10 minutes) and metadata attributes (e.g., os.type). Supports filtering via a filter expression, filtering by host status, custom groupBy to aggregate hosts by any attribute, ordering by any of the five metrics, and pagination via offset/limit. The response type is 'list' for the default host.name grouping or 'grouped_list' for custom groupBy keys. Also reports missing required metrics and whether the requested time range falls before the data retention boundary.
* Returns a paginated list of hosts with key infrastructure metrics: CPU usage (%), memory usage (%), I/O wait (%), disk usage (%), and 15-minute load average. Each host includes its current status (active/inactive based on metrics reported in the last 10 minutes) and metadata attributes (e.g., os.type). Supports filtering via a filter expression, filtering by host status, custom groupBy to aggregate hosts by any attribute, ordering by any of the five metrics, and pagination via offset/limit. The response type is 'list' for the default host.name grouping or 'grouped_list' for custom groupBy keys. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (cpu, memory, wait, load15, diskUsage) return -1 as a sentinel when no data is available for that field.
* @summary List Hosts for Infra Monitoring
*/
export const listHosts = (
@@ -104,3 +106,87 @@ export const useListHosts = <
return useMutation(mutationOptions);
};
/**
* Returns a paginated list of Kubernetes pods with key metrics: CPU usage, CPU request/limit utilization, memory working set, memory request/limit utilization, current pod phase (pending/running/succeeded/failed/unknown), and pod age (ms since start time). Each pod includes metadata attributes (namespace, node, workload owner such as deployment/statefulset/daemonset/job/cronjob, cluster). Supports filtering via a filter expression, custom groupBy to aggregate pods by any attribute, ordering by any of the six metrics (cpu, cpu_request, cpu_limit, memory, memory_request, memory_limit), and pagination via offset/limit. The response type is 'list' for the default k8s.pod.uid grouping (each row is one pod with its current phase) or 'grouped_list' for custom groupBy keys (each row aggregates pods in the group with per-phase counts: pendingPodCount, runningPodCount, succeededPodCount, failedPodCount, unknownPodCount derived from each pod's latest phase in the window). Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (podCPU, podCPURequest, podCPULimit, podMemory, podMemoryRequest, podMemoryLimit, podAge) return -1 as a sentinel when no data is available for that field.
* @summary List Pods for Infra Monitoring
*/
export const listPods = (
inframonitoringtypesPostablePodsDTO: BodyType<InframonitoringtypesPostablePodsDTO>,
signal?: AbortSignal,
) => {
return GeneratedAPIInstance<ListPods200>({
url: `/api/v2/infra_monitoring/pods`,
method: 'POST',
headers: { 'Content-Type': 'application/json' },
data: inframonitoringtypesPostablePodsDTO,
signal,
});
};
export const getListPodsMutationOptions = <
TError = ErrorType<RenderErrorResponseDTO>,
TContext = unknown,
>(options?: {
mutation?: UseMutationOptions<
Awaited<ReturnType<typeof listPods>>,
TError,
{ data: BodyType<InframonitoringtypesPostablePodsDTO> },
TContext
>;
}): UseMutationOptions<
Awaited<ReturnType<typeof listPods>>,
TError,
{ data: BodyType<InframonitoringtypesPostablePodsDTO> },
TContext
> => {
const mutationKey = ['listPods'];
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 listPods>>,
{ data: BodyType<InframonitoringtypesPostablePodsDTO> }
> = (props) => {
const { data } = props ?? {};
return listPods(data);
};
return { mutationFn, ...mutationOptions };
};
export type ListPodsMutationResult = NonNullable<
Awaited<ReturnType<typeof listPods>>
>;
export type ListPodsMutationBody =
BodyType<InframonitoringtypesPostablePodsDTO>;
export type ListPodsMutationError = ErrorType<RenderErrorResponseDTO>;
/**
* @summary List Pods for Infra Monitoring
*/
export const useListPods = <
TError = ErrorType<RenderErrorResponseDTO>,
TContext = unknown,
>(options?: {
mutation?: UseMutationOptions<
Awaited<ReturnType<typeof listPods>>,
TError,
{ data: BodyType<InframonitoringtypesPostablePodsDTO> },
TContext
>;
}): UseMutationResult<
Awaited<ReturnType<typeof listPods>>,
TError,
{ data: BodyType<InframonitoringtypesPostablePodsDTO> },
TContext
> => {
const mutationOptions = getListPodsMutationOptions(options);
return useMutation(mutationOptions);
};

View File

@@ -3243,6 +3243,108 @@ export interface InframonitoringtypesHostsDTO {
warning?: Querybuildertypesv5QueryWarnDataDTO;
}
export enum InframonitoringtypesPodPhaseDTO {
pending = 'pending',
running = 'running',
succeeded = 'succeeded',
failed = 'failed',
unknown = 'unknown',
'' = '',
}
/**
* @nullable
*/
export type InframonitoringtypesPodRecordDTOMeta = {
[key: string]: unknown;
} | null;
export interface InframonitoringtypesPodRecordDTO {
/**
* @type integer
*/
failedPodCount: number;
/**
* @type object
* @nullable true
*/
meta: InframonitoringtypesPodRecordDTOMeta;
/**
* @type integer
*/
pendingPodCount: number;
/**
* @type integer
* @format int64
*/
podAge: number;
/**
* @type number
* @format double
*/
podCPU: number;
/**
* @type number
* @format double
*/
podCPULimit: number;
/**
* @type number
* @format double
*/
podCPURequest: number;
/**
* @type number
* @format double
*/
podMemory: number;
/**
* @type number
* @format double
*/
podMemoryLimit: number;
/**
* @type number
* @format double
*/
podMemoryRequest: number;
podPhase: InframonitoringtypesPodPhaseDTO;
/**
* @type string
*/
podUID: string;
/**
* @type integer
*/
runningPodCount: number;
/**
* @type integer
*/
succeededPodCount: number;
/**
* @type integer
*/
unknownPodCount: number;
}
export interface InframonitoringtypesPodsDTO {
/**
* @type boolean
*/
endTimeBeforeRetention: boolean;
/**
* @type array
* @nullable true
*/
records: InframonitoringtypesPodRecordDTO[] | null;
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
*/
total: number;
type: InframonitoringtypesResponseTypeDTO;
warning?: Querybuildertypesv5QueryWarnDataDTO;
}
export interface InframonitoringtypesPostableHostsDTO {
/**
* @type integer
@@ -3271,6 +3373,34 @@ export interface InframonitoringtypesPostableHostsDTO {
start: number;
}
export interface InframonitoringtypesPostablePodsDTO {
/**
* @type integer
* @format int64
*/
end: number;
filter?: Querybuildertypesv5FilterDTO;
/**
* @type array
* @nullable true
*/
groupBy?: Querybuildertypesv5GroupByKeyDTO[] | null;
/**
* @type integer
*/
limit: number;
/**
* @type integer
*/
offset?: number;
orderBy?: Querybuildertypesv5OrderByDTO;
/**
* @type integer
* @format int64
*/
start: number;
}
export interface InframonitoringtypesRequiredMetricsCheckDTO {
/**
* @type array
@@ -5472,13 +5602,9 @@ export interface Sigv4SigV4ConfigDTO {
[key: string]: unknown;
}
/**
* @nullable
*/
export enum SpantypesFieldContextDTO {
attribute = 'attribute',
resource = 'resource',
null = null,
}
export interface SpantypesGettableSpanMapperGroupsDTO {
/**
@@ -5501,6 +5627,7 @@ export interface SpantypesPostableSpanMapperDTO {
}
export interface SpantypesPostableSpanMapperGroupDTO {
category: SpantypesSpanMapperGroupCategoryDTO;
condition: SpantypesSpanMapperGroupConditionDTO;
/**
* @type boolean
@@ -5551,18 +5678,16 @@ export interface SpantypesSpanMapperDTO {
updatedBy?: string;
}
/**
* @nullable
*/
export type SpantypesSpanMapperConfigDTO = {
export interface SpantypesSpanMapperConfigDTO {
/**
* @type array
* @nullable true
*/
sources: SpantypesSpanMapperSourceDTO[] | null;
} | null;
}
export interface SpantypesSpanMapperGroupDTO {
category: SpantypesSpanMapperGroupCategoryDTO;
condition: SpantypesSpanMapperGroupConditionDTO;
/**
* @type string
@@ -5600,10 +5725,11 @@ export interface SpantypesSpanMapperGroupDTO {
updatedBy?: string;
}
/**
* @nullable
*/
export type SpantypesSpanMapperGroupConditionDTO = {
export interface SpantypesSpanMapperGroupCategoryDTO {
[key: string]: unknown;
}
export interface SpantypesSpanMapperGroupConditionDTO {
/**
* @type array
* @nullable true
@@ -5614,7 +5740,7 @@ export type SpantypesSpanMapperGroupConditionDTO = {
* @nullable true
*/
resource: string[] | null;
} | null;
}
export enum SpantypesSpanMapperOperationDTO {
move = 'move',
@@ -7108,6 +7234,10 @@ export type GetMyServiceAccount200 = {
};
export type ListSpanMapperGroupsParams = {
/**
* @description undefined
*/
category?: SpantypesSpanMapperGroupCategoryDTO;
/**
* @type boolean
* @nullable true
@@ -7350,6 +7480,14 @@ export type ListHosts200 = {
status: string;
};
export type ListPods200 = {
data: InframonitoringtypesPodsDTO;
/**
* @type string
*/
status: string;
};
export type Livez200 = {
data: FactoryResponseDTO;
/**

View File

@@ -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();
});

View File

@@ -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,

View File

@@ -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: '' });
});
});

View File

@@ -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',

View File

@@ -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 });
});
});

View File

@@ -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]);

View File

@@ -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

View File

@@ -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);
}
});
});

View File

@@ -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',

View File

@@ -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();
});
});

View File

@@ -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,

View File

@@ -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) {

View File

@@ -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({

View File

@@ -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} />,
);

View File

@@ -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');

View File

@@ -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',

View File

@@ -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;

View File

@@ -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,

View File

@@ -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',

View File

@@ -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', () => {

View File

@@ -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()',
},

View File

@@ -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']);
});
});

View File

@@ -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();
});
});

View File

@@ -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(

View File

@@ -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();

View File

@@ -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 () => {

View File

@@ -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', () => {

View File

@@ -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', () => {

View File

@@ -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',

View File

@@ -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([]);
});
});
});

View File

@@ -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(() => {

View File

@@ -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'],

View File

@@ -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: [

View File

@@ -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" />);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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',

View File

@@ -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);

View File

@@ -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',

View File

@@ -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');

View File

@@ -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);

View File

@@ -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 "-"

View File

@@ -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 "-"

View File

@@ -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 === '>=');

View File

@@ -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');
});

View File

@@ -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');

View File

@@ -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);
});
});

View File

@@ -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 />,
{},

View File

@@ -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',

View File

@@ -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,
});

View File

@@ -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);
});
});
});

View File

@@ -113,7 +113,7 @@ describe('CustomDomainSettings', () => {
await user.click(screen.getByRole('button', { name: /apply changes/i }));
await waitFor(() => {
expect(capturedBody).toEqual({ name: 'myteam' });
expect(capturedBody).toStrictEqual({ name: 'myteam' });
});
});
@@ -143,9 +143,9 @@ describe('CustomDomainSettings', () => {
await user.type(input, 'myteam');
await user.click(screen.getByRole('button', { name: /apply changes/i }));
expect(
await screen.findByRole('button', { name: /contact support/i }),
).toBeInTheDocument();
await expect(
screen.findByRole('button', { name: /contact support/i }),
).resolves.toBeInTheDocument();
});
it('shows validation error when subdomain is less than 3 characters', async () => {
@@ -255,7 +255,7 @@ describe('CustomDomainSettings', () => {
},
});
expect(await screen.findByText('My Org Name')).toBeInTheDocument();
await expect(screen.findByText('My Org Name')).resolves.toBeInTheDocument();
});
it('falls back to customDomainSubdomain when org displayName is missing', async () => {
@@ -269,7 +269,7 @@ describe('CustomDomainSettings', () => {
appContextOverrides: { org: [] },
});
expect(await screen.findByText('custom-host')).toBeInTheDocument();
await expect(screen.findByText('custom-host')).resolves.toBeInTheDocument();
});
it('falls back to activeHost.name when neither org name nor custom domain exists', async () => {
@@ -294,7 +294,9 @@ describe('CustomDomainSettings', () => {
});
// 'accepted-starfish' is the default host's name
expect(await screen.findByText('accepted-starfish')).toBeInTheDocument();
await expect(
screen.findByText('accepted-starfish'),
).resolves.toBeInTheDocument();
});
it('does not render the card name row if workspaceName is totally falsy', async () => {

View File

@@ -155,7 +155,7 @@ describe('VariableItem Component', () => {
jest.clearAllMocks();
});
test('renders without crashing', () => {
it('renders without crashing', () => {
renderVariableItem();
expect(screen.getByText(TEXT.ALL_VARIABLES)).toBeInTheDocument();
@@ -165,7 +165,7 @@ describe('VariableItem Component', () => {
});
describe('Variable Name Validation', () => {
test('shows error when variable name already exists', () => {
it('shows error when variable name already exists', () => {
// Set validateName to return false (name exists)
const mockValidateName = jest.fn().mockReturnValue(false);
@@ -181,7 +181,7 @@ describe('VariableItem Component', () => {
// We won't check for button disabled state as it might be inconsistent in tests
});
test('allows save when current variable name is used', () => {
it('allows save when current variable name is used', () => {
// Mock validate to return false for all other names but true for own name
const mockValidateName = jest
.fn()
@@ -197,7 +197,7 @@ describe('VariableItem Component', () => {
expect(screen.queryByText(TEXT.VARIABLE_EXISTS)).not.toBeInTheDocument();
});
test('shows error when variable name contains whitespace', () => {
it('shows error when variable name contains whitespace', () => {
renderVariableItem({ ...basicVariableData, name: '' });
// Enter a name with whitespace
@@ -212,7 +212,7 @@ describe('VariableItem Component', () => {
expect(saveButton).toBeDisabled();
});
test('allows variable name without whitespace', () => {
it('allows variable name without whitespace', () => {
renderVariableItem({ ...basicVariableData, name: '' });
// Enter a valid name without whitespace
@@ -223,7 +223,7 @@ describe('VariableItem Component', () => {
expect(screen.queryByText(TEXT.VARIABLE_WHITESPACE)).not.toBeInTheDocument();
});
test('validates whitespace in auto-generated name for dynamic variables', () => {
it('validates whitespace in auto-generated name for dynamic variables', () => {
// Create a dynamic variable with empty name
const dynamicVariable: IDashboardVariable = {
...basicVariableData,
@@ -241,7 +241,7 @@ describe('VariableItem Component', () => {
});
describe('Dynamic Variable Attribute Key Validation', () => {
test('shows error when attribute key already exists', async () => {
it('shows error when attribute key already exists', async () => {
// Mock validateAttributeKey to return false (attribute key exists)
const mockValidateAttributeKey = jest.fn().mockReturnValue(false);
@@ -277,7 +277,7 @@ describe('VariableItem Component', () => {
expect(saveButton).toBeDisabled();
});
test('allows saving when attribute key is unique', async () => {
it('allows saving when attribute key is unique', async () => {
// Mock validateAttributeKey to return true (attribute key is unique)
const mockValidateAttributeKey = jest.fn().mockReturnValue(true);
@@ -315,7 +315,7 @@ describe('VariableItem Component', () => {
expect(saveButton).not.toBeDisabled();
});
test('allows same attribute key for current variable being edited', async () => {
it('allows same attribute key for current variable being edited', async () => {
// Mock validateAttributeKey to return true for same variable
const mockValidateAttributeKey = jest.fn().mockImplementation(
(attributeKey, currentVariableId) =>
@@ -348,7 +348,7 @@ describe('VariableItem Component', () => {
});
});
test('does not validate attribute key for non-dynamic variables', async () => {
it('does not validate attribute key for non-dynamic variables', async () => {
// Mock validateAttributeKey to return false (would show error for dynamic)
const mockValidateAttributeKey = jest.fn().mockReturnValue(false);
@@ -377,7 +377,7 @@ describe('VariableItem Component', () => {
});
describe('Variable Type Switching', () => {
test('switches to CUSTOM variable type correctly', () => {
it('switches to CUSTOM variable type correctly', () => {
renderVariableItem();
// Find the Query button
@@ -401,7 +401,7 @@ describe('VariableItem Component', () => {
expect(screen.getByText(TEXT.OPTIONS)).toBeInTheDocument();
});
test('switches to TEXTBOX variable type correctly', () => {
it('switches to TEXTBOX variable type correctly', () => {
renderVariableItem();
// Find and click Textbox button
@@ -424,7 +424,7 @@ describe('VariableItem Component', () => {
});
describe('MultiSelect and ALL Option', () => {
test('enables ALL option only when multiSelect is enabled', async () => {
it('enables ALL option only when multiSelect is enabled', async () => {
renderVariableItem();
// Initially, ALL option should not be visible
@@ -457,7 +457,7 @@ describe('VariableItem Component', () => {
});
});
test('disables ALL option when multiSelect is disabled', async () => {
it('disables ALL option when multiSelect is disabled', async () => {
// Create variable with multiSelect and showALLOption both enabled
const variable: IDashboardVariable = {
...basicVariableData,
@@ -501,7 +501,7 @@ describe('VariableItem Component', () => {
});
describe('Cancel and Navigation', () => {
test('calls onCancel when clicking All Variables button', () => {
it('calls onCancel when clicking All Variables button', () => {
renderVariableItem();
// Click All variables button
@@ -511,7 +511,7 @@ describe('VariableItem Component', () => {
expect(onCancel).toHaveBeenCalledTimes(1);
});
test('calls onCancel when clicking Discard button', () => {
it('calls onCancel when clicking Discard button', () => {
renderVariableItem();
// Click Discard button
@@ -550,7 +550,7 @@ describe('VariableItem Component', () => {
};
// Test for cyclic dependency detection
test('detects circular dependency and shows error message', async () => {
it('detects circular dependency and shows error message', async () => {
// Create variables with circular dependency
const variable1 = createVariable(
TEST_VAR_IDS.VAR1,
@@ -577,7 +577,7 @@ describe('VariableItem Component', () => {
});
// Test for saving with no circular dependency
test('allows saving when no circular dependency exists', async () => {
it('allows saving when no circular dependency exists', async () => {
// Create variables without circular dependency
const variable1 = createVariable(
TEST_VAR_IDS.VAR1,
@@ -608,7 +608,7 @@ describe('VariableItem Component', () => {
});
// Test with multiple variable formats in query
test('detects circular dependency with different variable formats', async () => {
it('detects circular dependency with different variable formats', async () => {
// Create variables with circular dependency using different formats
const variable1 = createVariable(
TEST_VAR_IDS.VAR1,
@@ -645,7 +645,7 @@ describe('VariableItem Component', () => {
});
describe('Textbox Variable Default Value Handling', () => {
test('saves textbox variable with defaultValue and selectedValue set to textboxValue', async () => {
it('saves textbox variable with defaultValue and selectedValue set to textboxValue', async () => {
const user = userEvent.setup();
const textboxVariable: IDashboardVariable = {
id: TEST_VAR_IDS.VAR1,
@@ -676,7 +676,7 @@ describe('VariableItem Component', () => {
);
});
test('saves textbox variable with empty values when textboxValue is empty', async () => {
it('saves textbox variable with empty values when textboxValue is empty', async () => {
const user = userEvent.setup();
const textboxVariable: IDashboardVariable = {
id: TEST_VAR_IDS.VAR1,
@@ -707,7 +707,7 @@ describe('VariableItem Component', () => {
);
});
test('updates textbox defaultValue and selectedValue when user changes textboxValue input', async () => {
it('updates textbox defaultValue and selectedValue when user changes textboxValue input', async () => {
const user = userEvent.setup();
const textboxVariable: IDashboardVariable = {
id: TEST_VAR_IDS.VAR1,
@@ -745,7 +745,7 @@ describe('VariableItem Component', () => {
);
});
test('non-textbox variables use variableDefaultValue instead of textboxValue', async () => {
it('non-textbox variables use variableDefaultValue instead of textboxValue', async () => {
const user = userEvent.setup();
const queryVariable: IDashboardVariable = {
id: TEST_VAR_IDS.VAR1,
@@ -780,7 +780,7 @@ describe('VariableItem Component', () => {
expect(savedVariable.defaultValue).not.toBe('should-not-be-used');
});
test('switching to textbox type sets defaultValue and selectedValue correctly on save', async () => {
it('switching to textbox type sets defaultValue and selectedValue correctly on save', async () => {
const user = userEvent.setup();
// Start with a QUERY variable
const queryVariable: IDashboardVariable = {

View File

@@ -38,7 +38,7 @@ function TableRow({ children, ...props }: RowProps): JSX.Element {
transition,
isDragging,
} = useSortable({
// @ts-ignore
// @ts-expect-error
id: props['data-row-key'],
});
@@ -148,7 +148,7 @@ function VariablesSettings({
});
if (name) {
// @ts-ignore
// @ts-expect-error
variableNamesMap[name] = name;
}
@@ -391,7 +391,7 @@ function VariablesSettings({
const variableName = updatedVariables[index].name;
if (variableName) {
// @ts-ignore
// @ts-expect-error
reArrangedVariables[variableName] = {
...updatedVariables[index],
order: index,

View File

@@ -109,11 +109,13 @@ describe('PublicDashboardSetting', () => {
).toBeInTheDocument();
});
expect(
await screen.findByRole('checkbox', { name: /enable time range/i }),
).toBeInTheDocument();
await expect(
screen.findByRole('checkbox', { name: /enable time range/i }),
).resolves.toBeInTheDocument();
expect(await screen.findByText(/default time range/i)).toBeInTheDocument();
await expect(
screen.findByText(/default time range/i),
).resolves.toBeInTheDocument();
expect(screen.getByText(/Last 30 minutes/i)).toBeInTheDocument();
@@ -123,9 +125,9 @@ describe('PublicDashboardSetting', () => {
).toBeInTheDocument();
});
expect(
await screen.findByRole('button', { name: /publish dashboard/i }),
).toBeInTheDocument();
await expect(
screen.findByRole('button', { name: /publish dashboard/i }),
).resolves.toBeInTheDocument();
});
});
@@ -149,9 +151,9 @@ describe('PublicDashboardSetting', () => {
).toBeInTheDocument();
});
expect(
await screen.findByRole('checkbox', { name: /enable time range/i }),
).toBeChecked();
await expect(
screen.findByRole('checkbox', { name: /enable time range/i }),
).resolves.toBeChecked();
await waitFor(() => {
expect(screen.getByText(/default time range/i)).toBeInTheDocument();
@@ -163,13 +165,13 @@ describe('PublicDashboardSetting', () => {
expect(screen.getByText(/Public Dashboard URL/i)).toBeInTheDocument();
});
expect(
await screen.findByRole('button', { name: /update published dashboard/i }),
).toBeInTheDocument();
await expect(
screen.findByRole('button', { name: /update published dashboard/i }),
).resolves.toBeInTheDocument();
expect(
await screen.findByRole('button', { name: /unpublish dashboard/i }),
).toBeInTheDocument();
await expect(
screen.findByRole('button', { name: /unpublish dashboard/i }),
).resolves.toBeInTheDocument();
});
});
@@ -249,7 +251,7 @@ describe('PublicDashboardSetting', () => {
rest.post(publicDashboardURL, async (req, res, ctx) => {
const body = await req.json();
createApiCalled = true;
expect(body).toEqual({
expect(body).toStrictEqual({
timeRangeEnabled: true,
defaultTimeRange: DEFAULT_TIME_RANGE,
});
@@ -318,7 +320,7 @@ describe('PublicDashboardSetting', () => {
await waitFor(() => {
expect(updateApiCalled).toBe(true);
expect(capturedRequestBody).toEqual({
expect(capturedRequestBody).toStrictEqual({
timeRangeEnabled: true,
defaultTimeRange: DEFAULT_TIME_RANGE,
});

View File

@@ -40,7 +40,7 @@ describe('VariableItem', () => {
useEffectSpy.mockRestore();
});
test('renders component with default props', () => {
it('renders component with default props', () => {
render(
<MockQueryClientProvider>
<VariableItem
@@ -54,7 +54,7 @@ describe('VariableItem', () => {
expect(screen.getByText('$testVariable')).toBeInTheDocument();
});
test('renders Input when the variable type is TEXTBOX', () => {
it('renders Input when the variable type is TEXTBOX', () => {
render(
<MockQueryClientProvider>
<VariableItem
@@ -69,7 +69,7 @@ describe('VariableItem', () => {
).toBeInTheDocument();
});
test('calls onValueUpdate when Input value changes and blurs', async () => {
it('calls onValueUpdate when Input value changes and blurs', async () => {
render(
<MockQueryClientProvider>
<VariableItem
@@ -102,7 +102,7 @@ describe('VariableItem', () => {
});
});
test('renders a Select element when variable type is CUSTOM', () => {
it('renders a Select element when variable type is CUSTOM', () => {
render(
<MockQueryClientProvider>
<VariableItem
@@ -117,7 +117,7 @@ describe('VariableItem', () => {
expect(screen.getByTestId('variable-select')).toBeInTheDocument();
});
test('renders a Select element with all selected', async () => {
it('renders a Select element with all selected', async () => {
const customVariableData = {
...mockCustomVariableData,
allSelected: true,
@@ -138,7 +138,7 @@ describe('VariableItem', () => {
expect(screen.getByText('ALL')).toBeInTheDocument();
});
test('calls useEffect when the component mounts', () => {
it('calls useEffect when the component mounts', () => {
render(
<MockQueryClientProvider>
<VariableItem

View File

@@ -272,7 +272,7 @@ describe('DashboardVariableSelection', () => {
);
});
expect(callOrder).toEqual([
expect(callOrder).toStrictEqual([
'updateDashboardVariablesStore',
'enqueueDescendantsOfVariable',
]);

View File

@@ -32,7 +32,7 @@ describe('VariableItem Default Value Selection Behavior', () => {
});
describe('Single Select Variables', () => {
test('should keep previous selection value', async () => {
it('should keep previous selection value', async () => {
const variable: IDashboardVariable = {
id: TEST_VARIABLE_ID,
name: TEST_VARIABLE_NAME,
@@ -51,10 +51,10 @@ describe('VariableItem Default Value Selection Behavior', () => {
expect(screen.getByTestId(VARIABLE_SELECT_TESTID)).toBeInTheDocument();
});
expect(await screen.findByText('option1')).toBeInTheDocument();
await expect(screen.findByText('option1')).resolves.toBeInTheDocument();
});
test('should auto-select first option when no previous and no default', async () => {
it('should auto-select first option when no previous and no default', async () => {
const variable: IDashboardVariable = {
id: TEST_VARIABLE_ID,
name: TEST_VARIABLE_NAME,
@@ -74,12 +74,12 @@ describe('VariableItem Default Value Selection Behavior', () => {
});
// With the new variable select strategy, the first option is auto-selected
expect(await screen.findByText('option1')).toBeInTheDocument();
await expect(screen.findByText('option1')).resolves.toBeInTheDocument();
});
});
describe('Multi Select Variables with ALL enabled', () => {
test('should show ALL when all options are selected', async () => {
it('should show ALL when all options are selected', async () => {
const variable: IDashboardVariable = {
id: TEST_VARIABLE_ID,
name: TEST_VARIABLE_NAME,
@@ -99,12 +99,12 @@ describe('VariableItem Default Value Selection Behavior', () => {
expect(screen.getByTestId(VARIABLE_SELECT_TESTID)).toBeInTheDocument();
});
expect(await screen.findByText('ALL')).toBeInTheDocument();
await expect(screen.findByText('ALL')).resolves.toBeInTheDocument();
});
});
describe('Multi Select Variables with ALL disabled', () => {
test('should show placeholder when no selection', async () => {
it('should show placeholder when no selection', async () => {
const variable: IDashboardVariable = {
id: TEST_VARIABLE_ID,
name: TEST_VARIABLE_NAME,
@@ -123,7 +123,7 @@ describe('VariableItem Default Value Selection Behavior', () => {
expect(screen.getByTestId(VARIABLE_SELECT_TESTID)).toBeInTheDocument();
});
expect(await screen.findByText('Select value')).toBeInTheDocument();
await expect(screen.findByText('Select value')).resolves.toBeInTheDocument();
});
});
});

View File

@@ -47,7 +47,7 @@ describe('dashboardVariables - utilities and processors', () => {
},
];
test.each(testCases)(
it.each(testCases)(
'should update variable node when $scenario',
({ nodeToUpdate, expected }) => {
const updatedVariables: string[] = [];
@@ -57,7 +57,7 @@ describe('dashboardVariables - utilities and processors', () => {
onUpdateVariableNode(nodeToUpdate, graph, topologicalOrder, callback);
expect(updatedVariables).toEqual(expected);
expect(updatedVariables).toStrictEqual(expected);
},
);
@@ -66,7 +66,7 @@ describe('dashboardVariables - utilities and processors', () => {
onUpdateVariableNode('http_status_code', graph, [], (node) =>
updatedVariables.push(node),
);
expect(updatedVariables).toEqual([]);
expect(updatedVariables).toStrictEqual([]);
});
});
@@ -87,11 +87,11 @@ describe('dashboardVariables - utilities and processors', () => {
environment: [],
};
expect(buildParentDependencyGraph(graph)).toEqual(expected);
expect(buildParentDependencyGraph(graph)).toStrictEqual(expected);
});
it('should handle empty graph', () => {
expect(buildParentDependencyGraph({})).toEqual({});
expect(buildParentDependencyGraph({})).toStrictEqual({});
});
});
@@ -142,13 +142,13 @@ describe('dashboardVariables - utilities and processors', () => {
},
};
expect(buildDependencyGraph(graph)).toEqual(expected);
expect(buildDependencyGraph(graph)).toStrictEqual(expected);
});
it('should return empty transitiveDescendants for an empty graph', () => {
const result = buildDependencyGraph({});
expect(result.transitiveDescendants).toEqual({});
expect(result.order).toEqual([]);
expect(result.transitiveDescendants).toStrictEqual({});
expect(result.order).toStrictEqual([]);
expect(result.hasCycle).toBe(false);
});
@@ -159,7 +159,7 @@ describe('dashboardVariables - utilities and processors', () => {
c: [],
};
const result = buildDependencyGraph(linearGraph);
expect(result.transitiveDescendants).toEqual({
expect(result.transitiveDescendants).toStrictEqual({
a: ['b', 'c'],
b: ['c'],
c: [],
@@ -174,13 +174,13 @@ describe('dashboardVariables - utilities and processors', () => {
d: [],
};
const result = buildDependencyGraph(diamondGraph);
expect(result.transitiveDescendants.a).toEqual(
expect(result.transitiveDescendants.a).toStrictEqual(
expect.arrayContaining(['b', 'c', 'd']),
);
expect(result.transitiveDescendants.a).toHaveLength(3);
expect(result.transitiveDescendants.b).toEqual(['d']);
expect(result.transitiveDescendants.c).toEqual(['d']);
expect(result.transitiveDescendants.d).toEqual([]);
expect(result.transitiveDescendants.b).toStrictEqual(['d']);
expect(result.transitiveDescendants.c).toStrictEqual(['d']);
expect(result.transitiveDescendants.d).toStrictEqual([]);
});
it('should handle disconnected components in transitiveDescendants', () => {
@@ -191,10 +191,10 @@ describe('dashboardVariables - utilities and processors', () => {
y: [],
};
const result = buildDependencyGraph(disconnectedGraph);
expect(result.transitiveDescendants.a).toEqual(['b']);
expect(result.transitiveDescendants.b).toEqual([]);
expect(result.transitiveDescendants.x).toEqual(['y']);
expect(result.transitiveDescendants.y).toEqual([]);
expect(result.transitiveDescendants.a).toStrictEqual(['b']);
expect(result.transitiveDescendants.b).toStrictEqual([]);
expect(result.transitiveDescendants.x).toStrictEqual(['y']);
expect(result.transitiveDescendants.y).toStrictEqual([]);
});
it('should return empty transitiveDescendants for all leaf nodes', () => {
@@ -204,7 +204,7 @@ describe('dashboardVariables - utilities and processors', () => {
c: [],
};
const result = buildDependencyGraph(leafOnlyGraph);
expect(result.transitiveDescendants).toEqual({
expect(result.transitiveDescendants).toStrictEqual({
a: [],
b: [],
c: [],
@@ -225,11 +225,11 @@ describe('dashboardVariables - utilities and processors', () => {
environment: [],
};
expect(buildDependencies(variables)).toEqual(expected);
expect(buildDependencies(variables)).toStrictEqual(expected);
});
it('should handle empty variables array', () => {
expect(buildDependencies([])).toEqual({});
expect(buildDependencies([])).toStrictEqual({});
});
});
});

View File

@@ -36,7 +36,7 @@ export const convertVariablesToDbFormat = (
variblesArr.reduce((result, obj: IDashboardVariable) => {
const { id } = obj;
// @ts-ignore
// @ts-expect-error
result[id] = obj;
return result;
}, {});

View File

@@ -81,7 +81,7 @@ describe('onUpdateVariableNode', () => {
onUpdateVariableNode('deployment', graph, topologicalOrder, callback);
expect(visited).toEqual(['deployment', 'namespace', 'service', 'pod']);
expect(visited).toStrictEqual(['deployment', 'namespace', 'service', 'pod']);
});
it('should call callback starting from a middle node', () => {
@@ -92,7 +92,7 @@ describe('onUpdateVariableNode', () => {
onUpdateVariableNode('namespace', graph, topologicalOrder, callback);
expect(visited).toEqual(['namespace', 'service', 'pod']);
expect(visited).toStrictEqual(['namespace', 'service', 'pod']);
});
it('should only call callback for the leaf node when updating leaf', () => {
@@ -103,7 +103,7 @@ describe('onUpdateVariableNode', () => {
onUpdateVariableNode('pod', graph, topologicalOrder, callback);
expect(visited).toEqual(['pod']);
expect(visited).toStrictEqual(['pod']);
});
it('should handle CUSTOM variable not in topologicalOrder by updating its children', () => {
@@ -116,7 +116,7 @@ describe('onUpdateVariableNode', () => {
onUpdateVariableNode('customVar', graph, topologicalOrder, callback);
// Should process namespace and its descendants (service, pod)
expect(visited).toEqual(['namespace', 'service', 'pod']);
expect(visited).toStrictEqual(['namespace', 'service', 'pod']);
});
it('should handle node not in graph gracefully', () => {
@@ -128,7 +128,7 @@ describe('onUpdateVariableNode', () => {
onUpdateVariableNode('unknownNode', graph, topologicalOrder, callback);
// Should not call callback for any node since unknownNode has no children
expect(visited).toEqual([]);
expect(visited).toStrictEqual([]);
});
it('should handle empty graph', () => {
@@ -140,7 +140,7 @@ describe('onUpdateVariableNode', () => {
onUpdateVariableNode('deployment', {}, topologicalOrder, callback);
// deployment is in topologicalOrder, so callback is called for it
expect(visited).toEqual(['deployment']);
expect(visited).toStrictEqual(['deployment']);
});
it('should handle empty topologicalOrder', () => {
@@ -151,7 +151,7 @@ describe('onUpdateVariableNode', () => {
onUpdateVariableNode('deployment', graph, [], callback);
expect(visited).toEqual([]);
expect(visited).toStrictEqual([]);
});
it('should handle CUSTOM variable with multiple children', () => {
@@ -173,7 +173,7 @@ describe('onUpdateVariableNode', () => {
);
// Should process namespace, service, and pod (descendants)
expect(visited).toEqual(['namespace', 'service', 'pod']);
expect(visited).toStrictEqual(['namespace', 'service', 'pod']);
});
});
@@ -200,11 +200,15 @@ function makeDynamicVar(
describe('mergeUniqueStrings', () => {
it('should merge two arrays and deduplicate', () => {
expect(mergeUniqueStrings(['a', 'b'], ['b', 'c'])).toEqual(['a', 'b', 'c']);
expect(mergeUniqueStrings(['a', 'b'], ['b', 'c'])).toStrictEqual([
'a',
'b',
'c',
]);
});
it('should convert numbers and booleans to strings', () => {
expect(mergeUniqueStrings([1, true, 'hello'], [2, false])).toEqual([
expect(mergeUniqueStrings([1, true, 'hello'], [2, false])).toStrictEqual([
'1',
'true',
'hello',
@@ -214,15 +218,15 @@ describe('mergeUniqueStrings', () => {
});
it('should deduplicate when number and its string form both appear', () => {
expect(mergeUniqueStrings([42], ['42'])).toEqual(['42']);
expect(mergeUniqueStrings([42], ['42'])).toStrictEqual(['42']);
});
it('should handle a single array', () => {
expect(mergeUniqueStrings(['x', 'y', 'x'])).toEqual(['x', 'y']);
expect(mergeUniqueStrings(['x', 'y', 'x'])).toStrictEqual(['x', 'y']);
});
it('should handle three or more arrays', () => {
expect(mergeUniqueStrings(['a'], ['b'], ['c'], ['a', 'c'])).toEqual([
expect(mergeUniqueStrings(['a'], ['b'], ['c'], ['a', 'c'])).toStrictEqual([
'a',
'b',
'c',
@@ -230,15 +234,19 @@ describe('mergeUniqueStrings', () => {
});
it('should return empty array when no arrays are provided', () => {
expect(mergeUniqueStrings()).toEqual([]);
expect(mergeUniqueStrings()).toStrictEqual([]);
});
it('should return empty array when all input arrays are empty', () => {
expect(mergeUniqueStrings([], [], [])).toEqual([]);
expect(mergeUniqueStrings([], [], [])).toStrictEqual([]);
});
it('should preserve order of first occurrence', () => {
expect(mergeUniqueStrings(['c', 'a'], ['b', 'a'])).toEqual(['c', 'a', 'b']);
expect(mergeUniqueStrings(['c', 'a'], ['b', 'a'])).toStrictEqual([
'c',
'a',
'b',
]);
});
});

View File

@@ -424,7 +424,7 @@ describe('Panel Management Tests', () => {
);
// Should return dashboard unchanged
expect(updatedDashboard).toEqual(dashboard);
expect(updatedDashboard).toStrictEqual(dashboard);
});
it('should handle undefined dashboard gracefully', () => {

View File

@@ -33,6 +33,7 @@ export default function ChartWrapper({
children,
layoutChildren,
yAxisUnit,
groupBy,
customTooltip,
pinnedTooltipElement,
'data-testid': testId,
@@ -68,8 +69,9 @@ export default function ChartWrapper({
const syncMetadata = useMemo(
() => ({
yAxisUnit,
groupBy,
}),
[yAxisUnit],
[yAxisUnit, groupBy],
);
return (

View File

@@ -6,6 +6,7 @@ import {
DashboardCursorSync,
TooltipClickData,
} from 'lib/uPlotV2/plugins/TooltipPlugin/types';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
interface BaseChartProps {
width: number;
@@ -38,6 +39,7 @@ interface UPlotBasedChartProps {
interface UPlotChartDataProps {
yAxisUnit?: string;
decimalPrecision?: PrecisionOption;
groupBy?: BaseAutocompleteData[];
}
export interface TimeSeriesChartProps

View File

@@ -13,7 +13,7 @@ describe('stackUtils', () => {
[4, 5, 6],
];
const { data: result } = stack(data, neverOmit);
expect(result[0]).toEqual([100, 200, 300]);
expect(result[0]).toStrictEqual([100, 200, 300]);
});
it('stacks value series cumulatively (last = raw, first = total)', () => {
@@ -26,9 +26,9 @@ describe('stackUtils', () => {
];
const { data: result } = stack(data, neverOmit);
// result[1] = s1+s2+s3, result[2] = s2+s3, result[3] = s3
expect(result[1]).toEqual([12, 15, 18]); // 1+4+7, 2+5+8, 3+6+9
expect(result[2]).toEqual([11, 13, 15]); // 4+7, 5+8, 6+9
expect(result[3]).toEqual([7, 8, 9]);
expect(result[1]).toStrictEqual([12, 15, 18]); // 1+4+7, 2+5+8, 3+6+9
expect(result[2]).toStrictEqual([11, 13, 15]); // 4+7, 5+8, 6+9
expect(result[3]).toStrictEqual([7, 8, 9]);
});
it('treats null values as 0 when stacking', () => {
@@ -38,8 +38,8 @@ describe('stackUtils', () => {
[null, 10],
];
const { data: result } = stack(data, neverOmit);
expect(result[1]).toEqual([1, 10]); // total
expect(result[2]).toEqual([0, 10]); // last series with null→0
expect(result[1]).toStrictEqual([1, 10]); // total
expect(result[2]).toStrictEqual([0, 10]); // last series with null→0
});
it('copies omitted series as-is without accumulating', () => {
@@ -53,9 +53,9 @@ describe('stackUtils', () => {
const omitSeries2 = (i: number): boolean => i === 2;
const { data: result } = stack(data, omitSeries2);
// series 3 raw: [1, 2]; series 2 omitted: [100, 200] as-is; series 1 stacked with s3: [11, 22]
expect(result[1]).toEqual([11, 22]); // 10+1, 20+2
expect(result[2]).toEqual([100, 200]); // copied, not stacked
expect(result[3]).toEqual([1, 2]);
expect(result[1]).toStrictEqual([11, 22]); // 10+1, 20+2
expect(result[2]).toStrictEqual([100, 200]); // copied, not stacked
expect(result[3]).toStrictEqual([1, 2]);
});
it('returns bands between consecutive visible series when none omitted', () => {
@@ -66,7 +66,7 @@ describe('stackUtils', () => {
[5, 6],
];
const { bands } = stack(data, neverOmit);
expect(bands).toEqual([{ series: [1, 2] }, { series: [2, 3] }]);
expect(bands).toStrictEqual([{ series: [1, 2] }, { series: [2, 3] }]);
});
it('returns bands only between visible series when some are omitted', () => {
@@ -74,7 +74,7 @@ describe('stackUtils', () => {
const data: AlignedData = [[0], [1], [2], [3], [4]];
const omitSeries2 = (i: number): boolean => i === 2;
const { bands } = stack(data, omitSeries2);
expect(bands).toEqual([{ series: [1, 3] }, { series: [3, 4] }]);
expect(bands).toStrictEqual([{ series: [1, 3] }, { series: [3, 4] }]);
});
it('returns empty bands when only one value series', () => {
@@ -83,30 +83,30 @@ describe('stackUtils', () => {
[1, 2],
];
const { bands } = stack(data, neverOmit);
expect(bands).toEqual([]);
expect(bands).toStrictEqual([]);
});
});
describe('getInitialStackedBands', () => {
it('returns one band between each consecutive pair for seriesCount 3', () => {
expect(getInitialStackedBands(3)).toEqual([
expect(getInitialStackedBands(3)).toStrictEqual([
{ series: [1, 2] },
{ series: [2, 3] },
]);
});
it('returns empty array for seriesCount 0 or 1', () => {
expect(getInitialStackedBands(0)).toEqual([]);
expect(getInitialStackedBands(1)).toEqual([]);
expect(getInitialStackedBands(0)).toStrictEqual([]);
expect(getInitialStackedBands(1)).toStrictEqual([]);
});
it('returns single band for seriesCount 2', () => {
expect(getInitialStackedBands(2)).toEqual([{ series: [1, 2] }]);
expect(getInitialStackedBands(2)).toStrictEqual([{ series: [1, 2] }]);
});
it('returns bands [1,2], [2,3], ..., [n-1, n] for seriesCount n', () => {
const bands = getInitialStackedBands(5);
expect(bands).toEqual([
expect(bands).toStrictEqual([
{ series: [1, 2] },
{ series: [2, 3] },
{ series: [3, 4] },

View File

@@ -119,9 +119,9 @@ describe('useBarChartStacking', () => {
}),
);
// Still returns stacked data (computed in useMemo); no hooks registered
expect(result.current[0]).toEqual([0, 1]);
expect(result.current[1]).toEqual([5, 7]); // stacked
expect(result.current[2]).toEqual([4, 5]);
expect(result.current[0]).toStrictEqual([0, 1]);
expect(result.current[1]).toStrictEqual([5, 7]); // stacked
expect(result.current[2]).toStrictEqual([4, 5]);
});
it('returns stacked data when isStackedBarChart is true and multiple value series', () => {
@@ -138,10 +138,10 @@ describe('useBarChartStacking', () => {
config: null,
}),
);
expect(result.current[0]).toEqual([0, 1, 2]);
expect(result.current[1]).toEqual([12, 15, 18]); // s1+s2+s3
expect(result.current[2]).toEqual([11, 13, 15]); // s2+s3
expect(result.current[3]).toEqual([7, 8, 9]);
expect(result.current[0]).toStrictEqual([0, 1, 2]);
expect(result.current[1]).toStrictEqual([12, 15, 18]); // s1+s2+s3
expect(result.current[2]).toStrictEqual([11, 13, 15]); // s2+s3
expect(result.current[3]).toStrictEqual([7, 8, 9]);
});
it('returns data as-is when only one value series (no stacking needed)', () => {
@@ -156,7 +156,7 @@ describe('useBarChartStacking', () => {
config: null,
}),
);
expect(result.current).toEqual(data);
expect(result.current).toStrictEqual(data);
});
it('registers setData and setSeries hooks when isStackedBarChart and config provided', () => {

View File

@@ -113,6 +113,10 @@ function BarPanel(props: PanelWrapperProps): JSX.Element {
uPlotRef.current = plot;
}, []);
const groupBy = useMemo(() => {
return widget.query.builder.queryData[0].groupBy;
}, [widget.query]);
return (
<div className="panel-container" ref={graphRef}>
{containerDimensions.width > 0 && containerDimensions.height > 0 && (
@@ -128,6 +132,7 @@ function BarPanel(props: PanelWrapperProps): JSX.Element {
width={containerDimensions.width}
height={containerDimensions.height}
layoutChildren={layoutChildren}
groupBy={groupBy}
isStackedBarChart={widget.stackedBarChart ?? false}
yAxisUnit={widget.yAxisUnit}
decimalPrecision={widget.decimalPrecision}

View File

@@ -105,6 +105,7 @@ export function prepareBarPanelConfig({
colorMapping: widget.customLegendColors ?? {},
isDarkMode,
stepInterval: currentStepInterval,
metric: series.metric,
});
});

View File

@@ -104,6 +104,10 @@ function TimeSeriesPanel(props: PanelWrapperProps): JSX.Element {
widget.decimalPrecision,
]);
const groupBy = useMemo(() => {
return widget.query.builder.queryData[0].groupBy;
}, [widget.query]);
return (
<div className="panel-container" ref={graphRef}>
{containerDimensions.width > 0 && containerDimensions.height > 0 && (
@@ -117,6 +121,7 @@ function TimeSeriesPanel(props: PanelWrapperProps): JSX.Element {
yAxisUnit={widget.yAxisUnit}
decimalPrecision={widget.decimalPrecision}
data={chartData as uPlot.AlignedData}
groupBy={groupBy}
width={containerDimensions.width}
height={containerDimensions.height}
layoutChildren={layoutChildren}

View File

@@ -83,7 +83,7 @@ describe('TimeSeriesPanel utils', () => {
const data = prepareChartData(apiResponse);
expect(data).toHaveLength(1);
expect(data[0]).toEqual([]);
expect(data[0]).toStrictEqual([]);
});
it('returns timestamps and one series of y values for single series', () => {
@@ -102,8 +102,8 @@ describe('TimeSeriesPanel utils', () => {
const data = prepareChartData(apiResponse);
expect(data).toHaveLength(2);
expect(data[0]).toEqual([1000, 2000]);
expect(data[1]).toEqual([10, 20]);
expect(data[0]).toStrictEqual([1000, 2000]);
expect(data[1]).toStrictEqual([10, 20]);
});
it('merges timestamps and fills missing values with null for multiple series', () => {
@@ -128,11 +128,11 @@ describe('TimeSeriesPanel utils', () => {
const data = prepareChartData(apiResponse);
expect(data[0]).toEqual([1000, 2000, 3000]);
expect(data[0]).toStrictEqual([1000, 2000, 3000]);
// First series: 1, null, 3
expect(data[1]).toEqual([1, null, 3]);
expect(data[1]).toStrictEqual([1, null, 3]);
// Second series: 10, 20, null
expect(data[2]).toEqual([10, 20, null]);
expect(data[2]).toStrictEqual([10, 20, null]);
});
});

View File

@@ -131,6 +131,7 @@ export const prepareUPlotConfig = ({
pointSize: 5,
fillMode: widget.fillMode || FillMode.None,
isDarkMode,
metric: series.metric,
});
});

View File

@@ -62,7 +62,7 @@ describe('legendVisibilityUtils', () => {
const result = getStoredSeriesVisibility('widget-1');
expect(result).not.toBeNull();
expect(result).toEqual([
expect(result).toStrictEqual([
{ label: 'CPU', show: true },
{ label: 'Memory', show: false },
]);
@@ -85,7 +85,7 @@ describe('legendVisibilityUtils', () => {
const result = getStoredSeriesVisibility('widget-1');
expect(result).not.toBeNull();
expect(result).toEqual([
expect(result).toStrictEqual([
{ label: 'CPU', show: true },
{ label: 'CPU', show: false },
{ label: 'Memory', show: false },
@@ -128,7 +128,7 @@ describe('legendVisibilityUtils', () => {
const stored = getStoredSeriesVisibility('widget-1');
expect(stored).not.toBeNull();
expect(stored).toEqual([
expect(stored).toStrictEqual([
{ label: 'CPU', show: true },
{ label: 'Memory', show: false },
]);
@@ -150,7 +150,7 @@ describe('legendVisibilityUtils', () => {
const stored = getStoredSeriesVisibility('widget-new');
expect(stored).not.toBeNull();
expect(stored).toEqual([{ label: 'CPU', show: false }]);
expect(stored).toStrictEqual([{ label: 'CPU', show: false }]);
});
it('updates existing widget visibility when entry already exists', () => {
@@ -176,7 +176,7 @@ describe('legendVisibilityUtils', () => {
const stored = getStoredSeriesVisibility('widget-1');
expect(stored).not.toBeNull();
expect(stored).toEqual([
expect(stored).toStrictEqual([
{ label: 'CPU', show: false },
{ label: 'Memory', show: true },
]);
@@ -202,7 +202,7 @@ describe('legendVisibilityUtils', () => {
const stored = getStoredSeriesVisibility('widget-1');
expect(stored).not.toBeNull();
expect(stored).toEqual([
expect(stored).toStrictEqual([
{ label: 'x-axis', show: true },
{ label: 'CPU', show: false },
]);
@@ -232,10 +232,10 @@ describe('legendVisibilityUtils', () => {
{ label: 'B', show: true },
]);
expect(getStoredSeriesVisibility('widget-a')).toEqual([
expect(getStoredSeriesVisibility('widget-a')).toStrictEqual([
{ label: 'A', show: true },
]);
expect(getStoredSeriesVisibility('widget-b')).toEqual([
expect(getStoredSeriesVisibility('widget-b')).toStrictEqual([
{ label: 'B', show: true },
]);
});
@@ -252,7 +252,7 @@ describe('legendVisibilityUtils', () => {
);
const [_, value] = (localStorage.setItem as jest.Mock).mock.calls[0];
expect((): void => JSON.parse(value)).not.toThrow();
expect(JSON.parse(value)).toEqual([
expect(JSON.parse(value)).toStrictEqual([
{ name: 'widget-1', dataIndex: [{ label: 'CPU', show: true }] },
]);
});
@@ -263,7 +263,7 @@ describe('legendVisibilityUtils', () => {
const raw = localStorage.getItem(storageKey);
expect(raw).not.toBeNull();
const parsed = JSON.parse(raw ?? '[]');
expect(parsed).toEqual([{ name: 'widget-1', dataIndex: [] }]);
expect(parsed).toStrictEqual([{ name: 'widget-1', dataIndex: [] }]);
expect(getStoredSeriesVisibility('widget-1')).toBeNull();
});
});

View File

@@ -188,7 +188,9 @@ describe('ForgotPassword Component', () => {
const submitButton = screen.getByTestId('forgot-password-submit');
await user.click(submitButton);
expect(await screen.findByText(/check your email/i)).toBeInTheDocument();
await expect(
screen.findByText(/check your email/i),
).resolves.toBeInTheDocument();
expect(
screen.getByText(/we've sent a password reset link/i),
).toBeInTheDocument();
@@ -208,7 +210,9 @@ describe('ForgotPassword Component', () => {
const submitButton = screen.getByTestId('forgot-password-submit');
await user.click(submitButton);
expect(await screen.findByTestId('back-to-login')).toBeInTheDocument();
await expect(
screen.findByTestId('back-to-login'),
).resolves.toBeInTheDocument();
});
it('redirects to login when clicking back to login on success screen', async () => {
@@ -225,7 +229,9 @@ describe('ForgotPassword Component', () => {
const submitButton = screen.getByTestId('forgot-password-submit');
await user.click(submitButton);
expect(await screen.findByTestId('back-to-login')).toBeInTheDocument();
await expect(
screen.findByTestId('back-to-login'),
).resolves.toBeInTheDocument();
const backToLoginButton = screen.getByTestId('back-to-login');
await user.click(backToLoginButton);
@@ -250,7 +256,9 @@ describe('ForgotPassword Component', () => {
const submitButton = screen.getByTestId('forgot-password-submit');
await user.click(submitButton);
expect(await screen.findByText(/user not found/i)).toBeInTheDocument();
await expect(
screen.findByText(/user not found/i),
).resolves.toBeInTheDocument();
});
it('displays error message when API returns server error', async () => {
@@ -263,9 +271,9 @@ describe('ForgotPassword Component', () => {
const submitButton = screen.getByTestId('forgot-password-submit');
await user.click(submitButton);
expect(
await screen.findByText(/internal server error occurred/i),
).toBeInTheDocument();
await expect(
screen.findByText(/internal server error occurred/i),
).resolves.toBeInTheDocument();
});
it('clears error message on new submission attempt', async () => {
@@ -295,7 +303,9 @@ describe('ForgotPassword Component', () => {
const submitButton = screen.getByTestId('forgot-password-submit');
await user.click(submitButton);
expect(await screen.findByText(/user not found/i)).toBeInTheDocument();
await expect(
screen.findByText(/user not found/i),
).resolves.toBeInTheDocument();
// Click submit again
await user.click(submitButton);
@@ -303,7 +313,9 @@ describe('ForgotPassword Component', () => {
await waitFor(() => {
expect(screen.queryByText(/user not found/i)).not.toBeInTheDocument();
});
expect(await screen.findByText(/check your email/i)).toBeInTheDocument();
await expect(
screen.findByText(/check your email/i),
).resolves.toBeInTheDocument();
});
});
@@ -336,7 +348,9 @@ describe('ForgotPassword Component', () => {
await user.click(submitButton);
// Button should show loading state
expect(await screen.findByText(/sending\.\.\./i)).toBeInTheDocument();
await expect(
screen.findByText(/sending\.\.\./i),
).resolves.toBeInTheDocument();
});
it('disables submit button during loading', async () => {

View File

@@ -139,8 +139,8 @@ function ChartPreview({
if (startTime && endTime && startTime !== endTime) {
dispatch(
UpdateTimeInterval('custom', [
parseInt(getTimeString(startTime), 10),
parseInt(getTimeString(endTime), 10),
Number.parseInt(getTimeString(startTime), 10),
Number.parseInt(getTimeString(endTime), 10),
]),
);
}

View File

@@ -76,7 +76,7 @@ describe('usePrefillAlertConditions', () => {
builder: { queryData: [{ reduceTo: 'p90' }] },
} as any),
);
expect(result.current.matchType).toBe(null);
expect(result.current.matchType).toBeNull();
});
it('returns the correct matchType for multiple queries with same time aggregation', () => {
@@ -112,7 +112,7 @@ describe('usePrefillAlertConditions', () => {
},
} as any),
);
expect(result.current.matchType).toBe(null);
expect(result.current.matchType).toBeNull();
});
it('returns the correct op, target, targetUnit from the higher priority threshold for multiple thresholds', () => {

View File

@@ -370,7 +370,7 @@ function FormAlertRules({
// onQueryCategoryChange handles changes to query category
// in state as well as sets additional defaults
const onQueryCategoryChange = (val: EQueryType): void => {
const element = document.getElementById('top');
const element = document.querySelector('#top');
if (element) {
element.scrollIntoView({ behavior: 'smooth' });
}

View File

@@ -5,10 +5,10 @@ import { getUpdatedStepInterval } from './utils';
describe('getUpdatedStepInterval', () => {
it('should return 60', () => {
const result = getUpdatedStepInterval('5m0s');
expect(result).toEqual(60);
expect(result).toBe(60);
});
it('should return 60 for 10m0s', () => {
const result = getUpdatedStepInterval('10m0s');
expect(result).toEqual(60);
expect(result).toBe(60);
});
});

View File

@@ -44,7 +44,7 @@ describe('Table Panel utils', () => {
expect(getQueryLegend(query, 'A')).toBe('p99');
// should return undefined when legend not present
expect(getQueryLegend(query, 'B')).toBe(undefined);
expect(getQueryLegend(query, 'B')).toBeUndefined();
});
it('sorter function for table sorting', () => {

View File

@@ -108,7 +108,7 @@ describe('EntityLogs', () => {
});
await waitFor(() => {
expect(capturedQueryRangePayloads.length).toBe(1);
expect(capturedQueryRangePayloads).toHaveLength(1);
});
await waitFor(async () => {
@@ -131,7 +131,7 @@ describe('EntityLogs', () => {
});
await waitFor(() => {
expect(capturedQueryRangePayloads.length).toBe(2);
expect(capturedQueryRangePayloads).toHaveLength(2);
});
const firstPayload = capturedQueryRangePayloads[0];

View File

@@ -149,7 +149,7 @@ describe('ServiceDetails for S3 Sync service', () => {
expect(capturedPayload).not.toBeNull();
});
expect(capturedPayload).toEqual({
expect(capturedPayload).toStrictEqual({
config: {
aws: {
logs: {

View File

@@ -68,12 +68,12 @@ describe('filterAlerts', () => {
it('should return all alerts when filter is empty', () => {
const result = filterAlerts(mockAlerts, '');
expect(result).toEqual(mockAlerts);
expect(result).toStrictEqual(mockAlerts);
});
it('should return all alerts when filter is only whitespace', () => {
const result = filterAlerts(mockAlerts, ' ');
expect(result).toEqual(mockAlerts);
expect(result).toStrictEqual(mockAlerts);
});
it('should filter alerts by alert name', () => {

View File

@@ -251,20 +251,20 @@ describe('ContextLogRenderer', () => {
const afterQuery = (afterPayload.compositeQuery as any).queries[0].spec;
// Verify timestamps remain constant
expect(afterStart).toEqual(initialPayload.start);
expect(afterEnd).toEqual(initialPayload.end);
expect(afterStart).toStrictEqual(initialPayload.start);
expect(afterEnd).toStrictEqual(initialPayload.end);
// Verify offset changes
expect(initialQuery.offset).toEqual(0);
expect(afterQuery.offset).toEqual(10);
expect(initialQuery.offset).toBe(0);
expect(afterQuery.offset).toBe(10);
// Verify filter changes
expect(initialQuery.filter.expression).toContain(expectedOpChange.before);
expect(afterQuery.filter.expression).toContain(expectedOpChange.after);
// Verify query structure remains consistent
expect(initialQuery.name).toEqual(afterQuery.name);
expect(initialQuery.signal).toEqual(afterQuery.signal);
expect(initialQuery.name).toStrictEqual(afterQuery.name);
expect(initialQuery.signal).toStrictEqual(afterQuery.signal);
};
it('should keep the start and end timestamps constant on clicking load more (prev / next) pages', async () => {

View File

@@ -10,20 +10,20 @@ import {
describe('recursiveParseJSON', () => {
it('should return an empty object if the input is not valid JSON', () => {
const result = recursiveParseJSON('not valid JSON');
expect(result).toEqual({});
expect(result).toStrictEqual({});
});
it('should return the parsed JSON object for valid JSON input', () => {
const jsonString = '{"name": "John", "age": 30}';
const result = recursiveParseJSON(jsonString);
expect(result).toEqual({ name: 'John', age: 30 });
expect(result).toStrictEqual({ name: 'John', age: 30 });
});
it('should recursively parse nested JSON objects', () => {
const jsonString =
'{"name": "John", "age": 30, "address": {"street": "123 Main St", "city": "Anytown", "state": "CA"}}';
const result = recursiveParseJSON(jsonString);
expect(result).toEqual({
expect(result).toStrictEqual({
name: 'John',
age: 30,
address: {
@@ -37,19 +37,21 @@ describe('recursiveParseJSON', () => {
it('should recursively parse nested JSON arrays', () => {
const jsonString = '[1, 2, [3, 4], {"foo": "bar"}]';
const result = recursiveParseJSON(jsonString);
expect(result).toEqual([1, 2, [3, 4], { foo: 'bar' }]);
expect(result).toStrictEqual([1, 2, [3, 4], { foo: 'bar' }]);
});
it('should recursively parse deeply nested JSON objects', () => {
const jsonString = '{"foo": {"bar": {"baz": {"qux": {"value": 42}}}}}';
const result = recursiveParseJSON(jsonString);
expect(result).toEqual({ foo: { bar: { baz: { qux: { value: 42 } } } } });
expect(result).toStrictEqual({
foo: { bar: { baz: { qux: { value: 42 } } } },
});
});
it('should handle JSON input that contains escaped characters', () => {
const jsonString = '{"name": "John\\", \\"Doe", "age": 30}';
const result = recursiveParseJSON(jsonString);
expect(result).toEqual({ name: 'John", "Doe', age: 30 });
expect(result).toStrictEqual({ name: 'John", "Doe', age: 30 });
});
});
@@ -72,14 +74,14 @@ describe('flattenObject in the objects recursively', () => {
f: 4,
};
expect(flattenObject(nestedObj)).toEqual(expected);
expect(flattenObject(nestedObj)).toStrictEqual(expected);
});
it('should return an empty object when input is empty', () => {
const nestedObj = {};
const expected = {};
expect(flattenObject(nestedObj)).toEqual(expected);
expect(flattenObject(nestedObj)).toStrictEqual(expected);
});
it('should handle non-nested objects correctly', () => {
@@ -94,7 +96,7 @@ describe('flattenObject in the objects recursively', () => {
c: 3,
};
expect(flattenObject(nestedObj)).toEqual(expected);
expect(flattenObject(nestedObj)).toStrictEqual(expected);
});
it('should handle null and undefined correctly', () => {
@@ -107,7 +109,7 @@ describe('flattenObject in the objects recursively', () => {
b: undefined,
};
expect(flattenObject(nestedObj)).toEqual(expected);
expect(flattenObject(nestedObj)).toStrictEqual(expected);
});
it('should handle arrays correctly', () => {
@@ -120,7 +122,7 @@ describe('flattenObject in the objects recursively', () => {
b: 2,
};
expect(flattenObject(objWithArray)).toEqual(expected);
expect(flattenObject(objWithArray)).toStrictEqual(expected);
});
it('should handle nested objects in arrays correctly', () => {
@@ -133,7 +135,7 @@ describe('flattenObject in the objects recursively', () => {
d: 3,
};
expect(flattenObject(objWithArray)).toEqual(expected);
expect(flattenObject(objWithArray)).toStrictEqual(expected);
});
it('should handle objects with arrays and nested objects correctly', () => {
@@ -150,7 +152,7 @@ describe('flattenObject in the objects recursively', () => {
e: 5,
};
expect(flattenObject(complexObj)).toEqual(expected);
expect(flattenObject(complexObj)).toStrictEqual(expected);
});
});

View File

@@ -287,7 +287,7 @@ export const aggregateAttributesResourcesToString = (logData: ILog): string => {
outputJson.scope = outputJson.scope || {};
Object.assign(outputJson.scope, logData[key as keyof ILog]);
} else {
// @ts-ignore
// @ts-expect-error
outputJson[key] = logData[key as keyof ILog];
}
});

View File

@@ -256,7 +256,7 @@ describe('LogExplorerQuerySection', () => {
VIEWS_TO_TEST.forEach((view) => {
rerender(<LogExplorerQuerySection selectedView={view} />);
expect(mockQueryBuilderContext.currentQuery).toEqual(initialQuery);
expect(mockQueryBuilderContext.currentQuery).toStrictEqual(initialQuery);
});
});

View File

@@ -350,7 +350,7 @@ describe('useInitialQuery - Priority-Based Resource Filtering', () => {
const serviceItems = calledWith.items.filter(
(item: TagFilterItem) => item.key?.key === 'service.name',
);
expect(serviceItems.length).toBe(1);
expect(serviceItems).toHaveLength(1);
// Verify no priority items (k8s, cloud, host, container) are included
const priorityItems = calledWith.items.filter(

View File

@@ -255,7 +255,7 @@ describe.skip('LogsExplorerViews Pagination', () => {
expect(
screen.queryByText('pending_data_placeholder'),
).not.toBeInTheDocument();
expect(capturedPayloads.length).toBe(1);
expect(capturedPayloads).toHaveLength(1);
});
// Verify the payload of the first call, expecting offset 0
@@ -285,7 +285,7 @@ describe.skip('LogsExplorerViews Pagination', () => {
// Verify the second page request was made
// Wait for the second API call to be captured after the scroll
await waitFor(() => {
expect(capturedPayloads.length).toBe(2);
expect(capturedPayloads).toHaveLength(2);
});
// Store the time range from the first payload, which should be consistent in subsequent requests
@@ -324,7 +324,7 @@ describe.skip('LogsExplorerViews Pagination', () => {
// Verify the third page request was made
// Wait for the third API call to be captured
await waitFor(() => {
expect(capturedPayloads.length).toBe(3);
expect(capturedPayloads).toHaveLength(3);
});
const thirdPayload = capturedPayloads[2];
// Verify the payload of the third call, expecting offset 200 and consistent time range
@@ -526,13 +526,13 @@ describe('Logs Explorer -> stage and run query', () => {
const secondPayload = capturedPayloads[capturedPayloads.length - 1];
// Verify that the timestamps have changed due to UpdateTimeInterval
expect(secondPayload.start).not.toEqual(initialStart);
expect(secondPayload.end).not.toEqual(initialEnd);
expect(secondPayload.start).not.toStrictEqual(initialStart);
expect(secondPayload.end).not.toStrictEqual(initialEnd);
// The timestamps should be different (the exact difference depends on the mock implementation)
// Note: The timestamps might go backwards if UpdateTimeInterval is not called properly
expect(secondPayload.start).not.toEqual(initialStart);
expect(secondPayload.end).not.toEqual(initialEnd);
expect(secondPayload.start).not.toStrictEqual(initialStart);
expect(secondPayload.end).not.toStrictEqual(initialEnd);
// Verify that the IDs have changed (this confirms the Stage & Run Query button worked)
expect(currentStagedQuery.id).not.toBe(initialStagedQueryId);

View File

@@ -183,7 +183,7 @@ describe('LogsExplorerViews -', () => {
// Test that the menu items are present
const expectedMenuItemsCount = 3;
const menuItems = document.querySelectorAll('.menu-items .item');
expect(menuItems.length).toBe(expectedMenuItemsCount);
expect(menuItems).toHaveLength(expectedMenuItemsCount);
// Test that the component renders without crashing
expect(queryByTestId(periscopeDownloadButtonTestId)).toBeInTheDocument();
@@ -429,7 +429,7 @@ describe('LogsExplorerViews -', () => {
expect(first.groupBy?.length ?? 0).toBe(0);
expect(first.having?.expression).toBe('');
// Default orderBy should be timestamp desc, then id desc
expect(first.orderBy).toEqual([
expect(first.orderBy).toStrictEqual([
{ columnName: 'timestamp', order: 'desc' },
{ columnName: 'id', order: 'desc' },
]);

View File

@@ -135,8 +135,8 @@ describe('MembersSettings (integration)', () => {
await user.click(screen.getByRole('button', { name: /invite member/i }));
expect(await screen.findAllByPlaceholderText('john@signoz.io')).toHaveLength(
3,
);
await expect(
screen.findAllByPlaceholderText('john@signoz.io'),
).resolves.toHaveLength(3);
});
});

View File

@@ -164,7 +164,7 @@ describe('TopOperation API Integration', () => {
// Verify that only the top_operations endpoint was called
expect(apiCalls).toHaveLength(1);
expect(apiCalls[0].endpoint).toBe(TOP_OPERATIONS_ENDPOINT);
expect(apiCalls[0].body).toEqual({
expect(apiCalls[0].body).toStrictEqual({
start: `${defaultApiCallExpectation.start}`,
end: `${defaultApiCallExpectation.end}`,
service: defaultApiCallExpectation.service,
@@ -198,7 +198,7 @@ describe('TopOperation API Integration', () => {
// Verify that the entry_point_operations endpoint was called
expect(apiCalls).toHaveLength(1);
expect(apiCalls[0].endpoint).toBe(ENTRY_POINT_OPERATIONS_ENDPOINT);
expect(apiCalls[0].body).toEqual({
expect(apiCalls[0].body).toStrictEqual({
start: `${defaultApiCallExpectation.start}`,
end: `${defaultApiCallExpectation.end}`,
service: defaultApiCallExpectation.service,

View File

@@ -7,7 +7,7 @@ import {
} from './utils';
describe('Error Rate', () => {
test('should return correct error rate', () => {
it('should return correct error rate', () => {
const list: TopOperationList = getTopOperationList({
errorCount: 10,
numCalls: 100,
@@ -16,35 +16,35 @@ describe('Error Rate', () => {
expect(getErrorRate(list)).toBe(10);
});
test('should handle no errors gracefully', () => {
it('should handle no errors gracefully', () => {
const list = getTopOperationList({ errorCount: 0, numCalls: 100 });
expect(getErrorRate(list)).toBe(0);
});
test('should handle zero calls', () => {
it('should handle zero calls', () => {
const list = getTopOperationList({ errorCount: 0, numCalls: 0 });
expect(getErrorRate(list)).toBe(0);
});
});
describe('getNearestHighestBucketValue', () => {
test('should return nearest higher bucket value', () => {
it('should return nearest higher bucket value', () => {
expect(getNearestHighestBucketValue(50, [10, 20, 30, 40, 60, 70])).toBe('60');
});
test('should return +Inf for value higher than any bucket', () => {
it('should return +Inf for value higher than any bucket', () => {
expect(getNearestHighestBucketValue(80, [10, 20, 30, 40, 60, 70])).toBe(
'+Inf',
);
});
test('should return the first bucket for value lower than all buckets', () => {
it('should return the first bucket for value lower than all buckets', () => {
expect(getNearestHighestBucketValue(5, [10, 20, 30, 40, 60, 70])).toBe('10');
});
});
describe('convertedTracesToDownloadData', () => {
test('should convert trace data correctly', () => {
it('should convert trace data correctly', () => {
const data = [
{
name: 'op1',
@@ -56,7 +56,7 @@ describe('convertedTracesToDownloadData', () => {
},
];
expect(convertedTracesToDownloadData(data)).toEqual([
expect(convertedTracesToDownloadData(data)).toStrictEqual([
{
Name: 'op1',
'P50 (in ms)': '50.00',

Some files were not shown because too many files have changed in this diff Show More