@oneuptime/common 14.0.3 → 14.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/DatabaseModels/Alert.ts +55 -0
- package/Models/DatabaseModels/DatabaseServer.ts +1650 -0
- package/Models/DatabaseModels/DatabaseServerEndpoint.ts +540 -0
- package/Models/DatabaseModels/DatabaseServerFeed.ts +625 -0
- package/Models/DatabaseModels/DatabaseServerLabelRule.ts +514 -0
- package/Models/DatabaseModels/DatabaseServerOwnerRule.ts +596 -0
- package/Models/DatabaseModels/DatabaseServerOwnerTeam.ts +491 -0
- package/Models/DatabaseModels/DatabaseServerOwnerUser.ts +490 -0
- package/Models/DatabaseModels/Incident.ts +55 -0
- package/Models/DatabaseModels/Index.ts +16 -0
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +26 -0
- package/Models/DatabaseModels/ScheduledMaintenance.ts +55 -0
- package/Models/DatabaseModels/TelemetryException.ts +2 -0
- package/Models/DatabaseModels/UserProjectSsoConsent.ts +146 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795000000000-AddDatabaseServerTables.ts +673 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795100000000-AddUserProjectSsoConsent.ts +51 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Middleware/MultipartFormData.ts +1 -1
- package/Server/Middleware/TelemetryIngest.ts +15 -8
- package/Server/Services/AlertReminderRuleService.ts +100 -24
- package/Server/Services/DatabaseServerEndpointService.ts +895 -0
- package/Server/Services/DatabaseServerFeedService.ts +128 -0
- package/Server/Services/DatabaseServerLabelRuleEngineService.ts +340 -0
- package/Server/Services/DatabaseServerLabelRuleService.ts +14 -0
- package/Server/Services/DatabaseServerOwnerRuleEngineService.ts +425 -0
- package/Server/Services/DatabaseServerOwnerRuleService.ts +14 -0
- package/Server/Services/DatabaseServerOwnerTeamService.ts +180 -0
- package/Server/Services/DatabaseServerOwnerUserService.ts +173 -0
- package/Server/Services/DatabaseServerService.ts +4546 -0
- package/Server/Services/DatabaseService.ts +14 -8
- package/Server/Services/DockerResourceService.ts +43 -2
- package/Server/Services/IncidentReminderRuleService.ts +103 -23
- package/Server/Services/Index.ts +16 -0
- package/Server/Services/InventoryItemService.ts +113 -5
- package/Server/Services/IoTDeviceService.ts +145 -37
- package/Server/Services/OpenTelemetryIngestService.ts +19 -0
- package/Server/Services/PodmanResourceService.ts +43 -2
- package/Server/Services/ScheduledMaintenanceReminderRuleService.ts +107 -23
- package/Server/Services/ServiceService.ts +1 -1
- package/Server/Services/TelemetryUsageBillingService.ts +29 -2
- package/Server/Services/UserProjectSsoConsentService.ts +74 -0
- package/Server/Services/UserService.ts +14 -1
- package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +18 -0
- package/Server/Types/Database/QueryHelper.ts +30 -1
- package/Server/Utils/AI/Toolbox/ResourceTools.ts +69 -1
- package/Server/Utils/Database/AffectedResourceRelations.ts +6 -0
- package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +188 -6
- package/Server/Utils/Monitor/MonitorAlert.ts +28 -1
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +2262 -755
- package/Server/Utils/Monitor/MonitorIncident.ts +28 -1
- package/Server/Utils/Monitor/MonitorMaintenanceSuppression.ts +268 -6
- package/Server/Utils/Monitor/MonitorResource.ts +47 -11
- package/Server/Utils/Monitor/MonitorResourceContext.ts +1 -0
- package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +239 -21
- package/Server/Utils/Monitor/PerSeriesResolutionRootCause.ts +43 -0
- package/Server/Utils/Monitor/SeriesResourceLabels.ts +291 -0
- package/Server/Utils/Monitor/SeriesResourceLinker.ts +111 -12
- package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +25 -0
- package/Server/Utils/StartServer.ts +26 -6
- package/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.ts +2 -0
- package/Server/Utils/Telemetry/DatabaseEndpointDiscovery.ts +688 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +5 -1
- package/Server/Utils/Telemetry/LogExceptionExtractor.ts +18 -1
- package/Server/Utils/Telemetry/ResourceEntityFilter.ts +175 -12
- package/Server/Utils/Telemetry/ResourceFacetResolver.ts +12 -0
- package/Server/Utils/Telemetry/ServiceDependencyDiscovery.ts +606 -36
- package/Server/Utils/Telemetry/Telemetry.ts +16 -0
- package/Server/Utils/Telemetry/TelemetryEntity.ts +22 -22
- package/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.ts +16 -10
- package/Tests/App/Accounts/SignedInRedirect.test.tsx +241 -0
- package/Tests/App/AdminDashboard/AdminHeaderSmallScreens.test.tsx +221 -4
- package/Tests/App/Dashboard/AIInsightsResourcePageContext.test.ts +42 -0
- package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +100 -0
- package/Tests/App/Dashboard/AffectedResourcesPicker.test.tsx +86 -0
- package/Tests/App/Dashboard/AffectedResourcesPickerHiddenTypes.test.tsx +2 -0
- package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +19 -0
- package/Tests/App/Dashboard/BreadcrumbCoverage.test.tsx +14 -0
- package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +26 -1
- package/Tests/App/Dashboard/DashboardAppSsoError.test.tsx +501 -0
- package/Tests/App/Dashboard/DashboardHeaderRequests.test.tsx +64 -1
- package/Tests/App/Dashboard/DashboardHeaderSmallScreens.test.tsx +178 -18
- package/Tests/App/Dashboard/DashboardMasterPageSsoRedirect.test.tsx +444 -0
- package/Tests/App/Dashboard/DashboardNavBarForeignHiddenRule.test.tsx +573 -0
- package/Tests/App/Dashboard/DatabaseChartAxes.test.tsx +431 -0
- package/Tests/App/Dashboard/DatabaseContainerDetailBadge.test.tsx +249 -0
- package/Tests/App/Dashboard/DatabaseDashboardE2EFixes.test.ts +681 -0
- package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +1801 -0
- package/Tests/App/Dashboard/DatabaseFleetSummaryRefresh.test.tsx +280 -0
- package/Tests/App/Dashboard/DatabaseFormHelpers.test.tsx +321 -0
- package/Tests/App/Dashboard/DatabaseMetricMonitorLink.test.tsx +795 -0
- package/Tests/App/Dashboard/DatabaseOverviewHeader.test.tsx +580 -0
- package/Tests/App/Dashboard/DatabaseRecommendationsEngineMetrics.test.ts +270 -0
- package/Tests/App/Dashboard/DatabaseServerComponents.test.tsx +1486 -0
- package/Tests/App/Dashboard/DatabaseServerEngineMetricsFilter.test.ts +223 -0
- package/Tests/App/Dashboard/DatabaseServerPresentation.test.ts +435 -0
- package/Tests/App/Dashboard/DatabaseServerSummary.test.ts +186 -0
- package/Tests/App/Dashboard/DatabaseServerTelemetryQueries.test.ts +1553 -0
- package/Tests/App/Dashboard/DatabaseTableTruncation.test.tsx +326 -0
- package/Tests/App/Dashboard/DatabaseTelemetryScope.test.ts +512 -0
- package/Tests/App/Dashboard/DatabaseTelemetryTabs.test.tsx +774 -0
- package/Tests/App/Dashboard/DatabaseViewLayout.test.tsx +233 -0
- package/Tests/App/Dashboard/DatabaseWorkloadBadge.test.tsx +972 -0
- package/Tests/App/Dashboard/DiscoveryReviewInventoryRefresh.test.tsx +5 -0
- package/Tests/App/Dashboard/DiscoveryReviewUnnamedHostHint.test.tsx +1061 -0
- package/Tests/App/Dashboard/EventOverlayScope.test.ts +147 -0
- package/Tests/App/Dashboard/EventOverlayScopeHook.test.tsx +1 -0
- package/Tests/App/Dashboard/LogsResourceFacetChips.test.tsx +1 -0
- package/Tests/App/Dashboard/MetricsViewerDrillDown.test.tsx +310 -0
- package/Tests/App/Dashboard/MetricsViewerEntityScopedRows.test.tsx +495 -0
- package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +132 -1
- package/Tests/App/Dashboard/NavigationSearchKeywords.test.tsx +5 -0
- package/Tests/App/Dashboard/ProductOrientation.test.tsx +4 -3
- package/Tests/App/Dashboard/RecommendationsLoadedContext.test.tsx +349 -0
- package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +62 -0
- package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +8 -1
- package/Tests/App/Dashboard/ResourceFeedPagesFilterSort.test.tsx +14 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +2 -0
- package/Tests/App/Dashboard/ServiceMapDatabaseLink.test.tsx +1085 -0
- package/Tests/App/Dashboard/TelemetryResourceRetentionSettings.test.tsx +10 -0
- package/Tests/App/Dashboard/TracesResourceFacets.test.tsx +2 -1
- package/Tests/App/StatusPage/StatusPageHeaderForeignHiddenRule.test.tsx +284 -0
- package/Tests/ClassStrings.ts +178 -0
- package/Tests/Fixtures/MobilePasskeyUser.json +1 -2
- package/Tests/ForeignHiddenRuleGuard.ts +2152 -0
- package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +2250 -0
- package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +24 -5
- package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
- package/Tests/RenderedMarkup.ts +518 -0
- package/Tests/ResponsiveVisibility.test.ts +490 -4
- package/Tests/ResponsiveVisibility.ts +505 -52
- package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
- package/Tests/Server/Infrastructure/Postgres/AddDatabaseServerTablesMigration.test.ts +541 -0
- package/Tests/Server/Infrastructure/Postgres/AddUserProjectSsoConsentMigration.test.ts +234 -0
- package/Tests/Server/Services/ContainerSnapshotUpsertPostgres.test.ts +319 -0
- package/Tests/Server/Services/CrossProjectRelationWriteGuard.test.ts +13 -0
- package/Tests/Server/Services/DatabaseServerEndpointService.test.ts +2033 -0
- package/Tests/Server/Services/DatabaseServerFeedAndOwnerServices.test.ts +529 -0
- package/Tests/Server/Services/DatabaseServerLifecycle.test.ts +3302 -0
- package/Tests/Server/Services/DatabaseServerRegistries.test.ts +603 -0
- package/Tests/Server/Services/DatabaseServerRuleEngines.test.ts +754 -0
- package/Tests/Server/Services/DatabaseServerService.test.ts +3558 -0
- package/Tests/Server/Services/DatabaseServerSqlPostgres.test.ts +2045 -0
- package/Tests/Server/Services/DatabaseServiceUpdateColumnsIfUnlockedPostgres.test.ts +362 -0
- package/Tests/Server/Services/DatabaseServiceUpdateColumnsIfUnlockedReply.test.ts +210 -0
- package/Tests/Server/Services/HookFreeWriteLengthClamp.test.ts +18 -0
- package/Tests/Server/Services/IncidentAlertSloLinkSurvivesEdit.test.ts +2 -0
- package/Tests/Server/Services/IncomingCallPolicyEscalationRuleTarget.test.ts +225 -0
- package/Tests/Server/Services/InventoryItemDisplayName.test.ts +280 -2
- package/Tests/Server/Services/InventoryUpsertSchemaParity.test.ts +8 -2
- package/Tests/Server/Services/IoTDeviceLatestMetricsPostgres.test.ts +689 -0
- package/Tests/Server/Services/IoTDeviceService.test.ts +379 -0
- package/Tests/Server/Services/LatestMetricsValuesShape.test.ts +360 -0
- package/Tests/Server/Services/LlmModelPriceService.test.ts +402 -0
- package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +7 -1
- package/Tests/Server/Services/OwnerRowUniqueness.test.ts +61 -9
- package/Tests/Server/Services/ReminderRuleLookupPostgres.test.ts +2250 -0
- package/Tests/Server/Services/ReminderRuleRefreshOpenSubjectsPaging.test.ts +653 -0
- package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +68 -20
- package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +3 -3
- package/Tests/Server/Services/TelemetryResourceFacetCounting.test.ts +9 -0
- package/Tests/Server/Services/UserProjectSsoConsentPostgres.test.ts +153 -0
- package/Tests/Server/Services/UserProjectSsoConsentService.test.ts +192 -0
- package/Tests/Server/Services/UserServiceFirstMasterAdminElection.test.ts +71 -0
- package/Tests/Server/Services/UserSignupIdTakeoverPostgres.test.ts +238 -0
- package/Tests/Server/Services/WorkspaceNotificationSummaryHelpers.test.ts +592 -0
- package/Tests/Server/Types/Billing/PayAsYouGoMeteredAuthorization.test.ts +3 -0
- package/Tests/Server/Types/Database/EventOverlayScopePostgres.test.ts +1 -0
- package/Tests/Server/Types/Database/FeedEventTypeFilterQuery.test.ts +11 -0
- package/Tests/Server/Types/Database/Permissions/InfrastructureOwnershipScope.test.ts +8 -0
- package/Tests/Server/Types/Database/QueryHelperBooleanForCriteriaBackedRule.test.ts +1094 -0
- package/Tests/Server/Utils/AI/ResourceTools.test.ts +134 -0
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.ts +41 -0
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaAnomalyUnits.test.ts +279 -9
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaDisplayContext.test.ts +933 -0
- package/Tests/Server/Utils/Monitor/DatabaseMaintenanceSuppression.test.ts +582 -0
- package/Tests/Server/Utils/Monitor/DatabaseServerMonitorLinking.test.ts +753 -0
- package/Tests/Server/Utils/Monitor/MonitorActionTimestamps.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorAlertCriteriaReferences.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +119 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +60 -25
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorAffectedResourceEdgeCases.test.ts +1719 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorKubernetesAffectedResources.test.ts +1447 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorKubernetesRatioEmail.test.ts +352 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPlatformMetricUnits.test.ts +717 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPlatformRawScan.test.ts +2125 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPlatformSeriesAffectedResources.test.ts +1288 -0
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorIncidentCriteriaReferences.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorIncidentMemberRoleMembership.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +88 -0
- package/Tests/Server/Utils/Monitor/MonitorMaintenanceSuppression.test.ts +205 -0
- package/Tests/Server/Utils/Monitor/MonitorResourceContext.test.ts +62 -0
- package/Tests/Server/Utils/Monitor/MonitorResourceDatabaseMaintenance.test.ts +803 -0
- package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +133 -3
- package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/PerSeriesRecoveryResolution.test.ts +472 -1
- package/Tests/Server/Utils/Monitor/PerSeriesSecondEntityAlerting.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +236 -2
- package/Tests/Server/Utils/SeriesResourceLabels.test.ts +70 -0
- package/Tests/Server/Utils/StartServerProtobufContentType.test.ts +54 -0
- package/Tests/Server/Utils/Telemetry/DatabaseEndpointDiscovery.test.ts +1895 -0
- package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +7 -0
- package/Tests/Server/Utils/Telemetry/LogExceptionExtractorSeverityGate.test.ts +90 -0
- package/Tests/Server/Utils/Telemetry/ResourceEntityFilter.test.ts +570 -0
- package/Tests/Server/Utils/Telemetry/ResourceFacetResolver.test.ts +97 -2
- package/Tests/Server/Utils/Telemetry/ServiceDependencyDiscovery.test.ts +1337 -0
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +295 -0
- package/Tests/Types/AI/AIResourceContext.test.ts +30 -0
- package/Tests/Types/DatabaseServer/DatabaseContainerClassifier.test.ts +3644 -0
- package/Tests/Types/DatabaseServer/DatabaseContainerCommand.test.ts +340 -0
- package/Tests/Types/DatabaseServer/DatabaseContainerCommandCorpus.ts +826 -0
- package/Tests/Types/DatabaseServer/DatabaseContainerCommandPostgres.test.ts +150 -0
- package/Tests/Types/DatabaseServer/DatabaseEndpoint.test.ts +2657 -0
- package/Tests/Types/DatabaseServer/DatabaseServerDiscoverySource.test.ts +64 -0
- package/Tests/Types/DatabaseServer/DatabaseServerEntityKeys.test.ts +952 -0
- package/Tests/Types/DatabaseServer/DatabaseServerMetricCatalog.test.ts +1161 -0
- package/Tests/Types/DatabaseServer/DatabaseSystem.test.ts +1514 -0
- package/Tests/Types/DatabaseServer/DatabaseTelemetryResolver.test.ts +1558 -0
- package/Tests/Types/Monitor/CephAlertTemplates.test.ts +255 -6
- package/Tests/Types/Monitor/DatabaseAlertTemplates.test.ts +2254 -0
- package/Tests/Types/Monitor/KubernetesAlertTemplates.test.ts +298 -0
- package/Tests/Types/Monitor/KubernetesMetricCatalog.test.ts +271 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +253 -9
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +13 -5
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +4 -2
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +111 -2
- package/Tests/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.test.ts +61 -0
- package/Tests/Types/Monitor/SeriesContext/SeriesLabelDisplay.test.ts +114 -0
- package/Tests/Types/Monitor/Utils/KubernetesAgentEmittedMetrics.ts +181 -0
- package/Tests/Types/NetworkDevice/DiscoveredHostNamingStatus.test.ts +401 -0
- package/Tests/Types/Telemetry/ResourceEntityFacet.test.ts +4 -1
- package/Tests/Types/Telemetry/ResourceFacetCatalog.test.ts +24 -2
- package/Tests/UI/Components/Card.test.tsx +93 -2
- package/Tests/UI/Components/FeedOptions.test.ts +6 -0
- package/Tests/UI/Components/FeedOptionsButton.test.tsx +8 -1
- package/Tests/UI/Components/ForeignHiddenRuleResilience.test.tsx +1147 -0
- package/Tests/UI/Components/HeaderRightRail.test.tsx +41 -1
- package/Tests/UI/Components/LogsEntityNames.test.ts +16 -1
- package/Tests/UI/Components/LogsFacetSidebarHiddenFacets.test.tsx +7 -3
- package/Tests/UI/Components/ResourceFacetConfigs.test.ts +2 -1
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
- package/Tests/UI/Components/SrOnlyForeignRule.test.tsx +994 -0
- package/Tests/UI/Components/StatusPage/ResourceListSelection.test.tsx +34 -1
- package/Tests/UI/Components/TelemetryFacetSidebarHiddenFacets.test.tsx +4 -1
- package/Tests/UI/ForeignHiddenRuleGuard.test.ts +1951 -0
- package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +19 -1
- package/Tests/UI/Rum/ReplayTabSwitcher.test.tsx +19 -1
- package/Tests/UI/TailwindPlayCdnForeignHiddenRule.test.ts +1005 -0
- package/Tests/UI/ThemeGroupHoverReveal.test.ts +847 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +70 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +21 -0
- package/Tests/UI/Utils/ModelAPISsoRedirect.test.ts +127 -0
- package/Tests/UI/Utils/Navigation.test.ts +102 -0
- package/Tests/UI/Utils/Telemetry/TelemetryEntityNames.test.ts +23 -0
- package/Tests/Utils/LabelRuleImportExport.test.ts +5 -0
- package/Tests/Utils/MetricUnitUtil.test.ts +227 -2
- package/Tests/Utils/Monitor/MetricValueFormatter.test.ts +288 -2
- package/Tests/Utils/Monitor/PlatformResourceIdentityAndUnits.test.ts +1559 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.test.ts +2546 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +315 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +336 -1
- package/Tests/Utils/NetworkDiscovery/NetbiosNameUtil.test.ts +244 -0
- package/Tests/Utils/ValueFormatter.test.ts +50 -0
- package/Tests/tsconfig.json +16 -0
- package/Types/AI/AIResourceContext.ts +7 -0
- package/Types/Dashboard/DashboardTemplates.ts +2 -1
- package/Types/DatabaseServer/DatabaseConnectionSpan.ts +77 -0
- package/Types/DatabaseServer/DatabaseContainerClassifier.ts +2068 -0
- package/Types/DatabaseServer/DatabaseContainerCommand.ts +801 -0
- package/Types/DatabaseServer/DatabaseEndpoint.ts +1943 -0
- package/Types/DatabaseServer/DatabaseServerDiscoverySource.ts +68 -0
- package/Types/DatabaseServer/DatabaseServerMetricCatalog.ts +966 -0
- package/Types/DatabaseServer/DatabaseSystem.ts +2124 -0
- package/Types/DatabaseServer/DatabaseTelemetryResolver.ts +555 -0
- package/Types/Email/EmailTemplateType.ts +1 -0
- package/Types/Monitor/CephAlertTemplates.ts +18 -0
- package/Types/Monitor/DatabaseAlertTemplates.ts +2020 -0
- package/Types/Monitor/KubernetesAlertTemplates.ts +64 -24
- package/Types/Monitor/KubernetesMetricCatalog.ts +118 -19
- package/Types/Monitor/MetricMonitor/MetricCriteriaContext.ts +14 -0
- package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +93 -10
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +109 -8
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +36 -7
- package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +43 -2
- package/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.ts +41 -6
- package/Types/Monitor/SeriesContext/SeriesLabelDisplay.ts +26 -0
- package/Types/NetworkDevice/DiscoveredHostNamingStatus.ts +147 -0
- package/Types/Permission.ts +267 -0
- package/Types/Probe/ProbeApiIngestResponse.ts +8 -0
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +10 -0
- package/Types/Rules/RuleRun.ts +12 -0
- package/Types/Telemetry/EntityType.ts +23 -0
- package/Types/Telemetry/ResourceFacetCatalog.ts +14 -0
- package/Types/Telemetry/ServiceType.ts +8 -0
- package/UI/Components/Banner/Banner.tsx +1 -1
- package/UI/Components/Card/Card.tsx +1 -1
- package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +2 -2
- package/UI/Components/Charts/Line/LineChart.tsx +7 -0
- package/UI/Components/CommandPalette/CommandPalette.tsx +1 -1
- package/UI/Components/Date/StartAndEndDate.tsx +5 -5
- package/UI/Components/Diagram/HorizontalStepChain.tsx +1 -1
- package/UI/Components/Feed/FeedOptionsButton.tsx +1 -1
- package/UI/Components/Forms/BasicForm.tsx +1 -1
- package/UI/Components/Header/Header.tsx +1 -1
- package/UI/Components/Header/HeaderIconDropdownButton.tsx +1 -1
- package/UI/Components/HeaderAlert/HeaderAlert.tsx +1 -1
- package/UI/Components/LogsViewer/components/FacetValueRow.tsx +1 -1
- package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +1 -1
- package/UI/Components/Modal/ModalFooter.tsx +1 -1
- package/UI/Components/ModelDetail/CardModelDetail.tsx +2 -2
- package/UI/Components/ModelTable/BaseModelTable.tsx +4 -4
- package/UI/Components/Navbar/NavBar.tsx +9 -2
- package/UI/Components/Navbar/NavBarMenuModal.tsx +2 -2
- package/UI/Components/Page/Page.tsx +1 -1
- package/UI/Components/Pagination/Pagination.tsx +3 -3
- package/UI/Components/ProgressButtons/ProgressButtonItem.tsx +1 -1
- package/UI/Components/SideMenu/SideMenu.tsx +4 -1
- package/UI/Components/StatusPage/ResourceGroupNavigator.tsx +4 -2
- package/UI/Components/StatusPage/ResourceList.tsx +6 -6
- package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +1 -1
- package/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.tsx +1 -1
- package/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.tsx +1 -1
- package/UI/Components/Workflow/ComponentsModal.tsx +2 -2
- package/UI/Components/Workflow/StepTraceViewer.tsx +1 -1
- package/UI/Styles/Theme.css +8 -1
- package/UI/Utils/Navigation.ts +89 -42
- package/UI/Utils/Telemetry/TelemetryEntityNames.ts +7 -0
- package/UI/Utils/TelemetryService.ts +4 -3
- package/Utils/LabelRuleImportExport.ts +2 -0
- package/Utils/MetricUnitUtil.ts +103 -11
- package/Utils/Monitor/MetricValueFormatter.ts +66 -13
- package/Utils/Monitor/PlatformMetricUnitUtil.ts +215 -0
- package/Utils/Monitor/PlatformResourceIdentity.ts +514 -0
- package/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.ts +425 -0
- package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +32 -0
- package/Utils/NetworkDiscovery/NetbiosNameUtil.ts +73 -0
- package/Utils/Telemetry/DatabaseServerEntityKeys.ts +275 -0
- package/Utils/Telemetry/EntityKey.ts +176 -0
- package/Utils/ValueFormatter.ts +16 -0
- package/build/dist/Models/DatabaseModels/Alert.js +54 -0
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseServer.js +1683 -0
- package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerEndpoint.js +559 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerEndpoint.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerLabelRule.js +522 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerLabelRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerRule.js +603 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerTeam.js +506 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerUser.js +505 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerUser.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Incident.js +54 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +16 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +54 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryException.js +2 -0
- package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserProjectSsoConsent.js +162 -0
- package/build/dist/Models/DatabaseModels/UserProjectSsoConsent.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795000000000-AddDatabaseServerTables.js +240 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795000000000-AddDatabaseServerTables.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795100000000-AddUserProjectSsoConsent.js +26 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795100000000-AddUserProjectSsoConsent.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/MultipartFormData.js +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +15 -8
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/AlertReminderRuleService.js +72 -23
- package/build/dist/Server/Services/AlertReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseServerEndpointService.js +694 -0
- package/build/dist/Server/Services/DatabaseServerEndpointService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerFeedService.js +110 -0
- package/build/dist/Server/Services/DatabaseServerFeedService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerLabelRuleEngineService.js +272 -0
- package/build/dist/Server/Services/DatabaseServerLabelRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerLabelRuleService.js +13 -0
- package/build/dist/Server/Services/DatabaseServerLabelRuleService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerOwnerRuleEngineService.js +340 -0
- package/build/dist/Server/Services/DatabaseServerOwnerRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerOwnerRuleService.js +13 -0
- package/build/dist/Server/Services/DatabaseServerOwnerRuleService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerOwnerTeamService.js +160 -0
- package/build/dist/Server/Services/DatabaseServerOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerOwnerUserService.js +153 -0
- package/build/dist/Server/Services/DatabaseServerOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerService.js +3272 -0
- package/build/dist/Server/Services/DatabaseServerService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseService.js +8 -4
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerResourceService.js +30 -3
- package/build/dist/Server/Services/DockerResourceService.js.map +1 -1
- package/build/dist/Server/Services/IncidentReminderRuleService.js +73 -23
- package/build/dist/Server/Services/IncidentReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +16 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/InventoryItemService.js +88 -5
- package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
- package/build/dist/Server/Services/IoTDeviceService.js +111 -24
- package/build/dist/Server/Services/IoTDeviceService.js.map +1 -1
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +24 -9
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/PodmanResourceService.js +30 -3
- package/build/dist/Server/Services/PodmanResourceService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js +75 -23
- package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/ServiceService.js +1 -1
- package/build/dist/Server/Services/ServiceService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryUsageBillingService.js +23 -2
- package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
- package/build/dist/Server/Services/UserProjectSsoConsentService.js +79 -0
- package/build/dist/Server/Services/UserProjectSsoConsentService.js.map +1 -0
- package/build/dist/Server/Services/UserService.js +13 -1
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +18 -0
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +26 -1
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js +46 -0
- package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js.map +1 -1
- package/build/dist/Server/Utils/Database/AffectedResourceRelations.js +6 -0
- package/build/dist/Server/Utils/Database/AffectedResourceRelations.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +134 -13
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +22 -6
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +1489 -524
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +22 -6
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js +196 -6
- package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +36 -9
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +175 -17
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/PerSeriesResolutionRootCause.js +29 -0
- package/build/dist/Server/Utils/Monitor/PerSeriesResolutionRootCause.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +211 -0
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +82 -10
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +25 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +20 -4
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js +2 -0
- package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/DatabaseEndpointDiscovery.js +442 -0
- package/build/dist/Server/Utils/Telemetry/DatabaseEndpointDiscovery.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +5 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js +15 -1
- package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +121 -5
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js +12 -0
- package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js +438 -36
- package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/Telemetry.js +12 -0
- package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +17 -18
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js +16 -10
- package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js.map +1 -1
- package/build/dist/Types/AI/AIResourceContext.js +7 -0
- package/build/dist/Types/AI/AIResourceContext.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js +2 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/DatabaseServer/DatabaseConnectionSpan.js +71 -0
- package/build/dist/Types/DatabaseServer/DatabaseConnectionSpan.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseContainerClassifier.js +1462 -0
- package/build/dist/Types/DatabaseServer/DatabaseContainerClassifier.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseContainerCommand.js +691 -0
- package/build/dist/Types/DatabaseServer/DatabaseContainerCommand.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseEndpoint.js +1407 -0
- package/build/dist/Types/DatabaseServer/DatabaseEndpoint.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseServerDiscoverySource.js +60 -0
- package/build/dist/Types/DatabaseServer/DatabaseServerDiscoverySource.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseServerMetricCatalog.js +804 -0
- package/build/dist/Types/DatabaseServer/DatabaseServerMetricCatalog.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseSystem.js +1860 -0
- package/build/dist/Types/DatabaseServer/DatabaseSystem.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseTelemetryResolver.js +406 -0
- package/build/dist/Types/DatabaseServer/DatabaseTelemetryResolver.js.map +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/Monitor/CephAlertTemplates.js +18 -0
- package/build/dist/Types/Monitor/CephAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/DatabaseAlertTemplates.js +1518 -0
- package/build/dist/Types/Monitor/DatabaseAlertTemplates.js.map +1 -0
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +57 -24
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/KubernetesMetricCatalog.js +104 -18
- package/build/dist/Types/Monitor/KubernetesMetricCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +80 -3
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +10 -3
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +29 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js +21 -6
- package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js.map +1 -1
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js +25 -0
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js.map +1 -1
- package/build/dist/Types/NetworkDevice/DiscoveredHostNamingStatus.js +136 -0
- package/build/dist/Types/NetworkDevice/DiscoveredHostNamingStatus.js.map +1 -0
- package/build/dist/Types/Permission.js +234 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +10 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
- package/build/dist/Types/Rules/RuleRun.js +4 -0
- package/build/dist/Types/Rules/RuleRun.js.map +1 -1
- package/build/dist/Types/Telemetry/EntityType.js +23 -0
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/Telemetry/ResourceFacetCatalog.js +14 -0
- package/build/dist/Types/Telemetry/ResourceFacetCatalog.js.map +1 -1
- package/build/dist/Types/Telemetry/ServiceType.js +8 -0
- package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
- package/build/dist/UI/Components/Banner/Banner.js +1 -1
- package/build/dist/UI/Components/Banner/Banner.js.map +1 -1
- package/build/dist/UI/Components/Card/Card.js +1 -1
- package/build/dist/UI/Components/Card/Card.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +2 -2
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js +1 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js +1 -1
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -1
- package/build/dist/UI/Components/Date/StartAndEndDate.js +5 -5
- package/build/dist/UI/Components/Date/StartAndEndDate.js.map +1 -1
- package/build/dist/UI/Components/Diagram/HorizontalStepChain.js +1 -1
- package/build/dist/UI/Components/Diagram/HorizontalStepChain.js.map +1 -1
- package/build/dist/UI/Components/Feed/FeedOptionsButton.js +1 -1
- package/build/dist/UI/Components/Feed/FeedOptionsButton.js.map +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +1 -1
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
- package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js +1 -1
- package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js +1 -1
- package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/Modal/ModalFooter.js +1 -1
- package/build/dist/UI/Components/Modal/ModalFooter.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +2 -2
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +4 -4
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBar.js +9 -2
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +2 -2
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
- package/build/dist/UI/Components/Page/Page.js +1 -1
- package/build/dist/UI/Components/Page/Page.js.map +1 -1
- package/build/dist/UI/Components/Pagination/Pagination.js +3 -3
- package/build/dist/UI/Components/Pagination/Pagination.js.map +1 -1
- package/build/dist/UI/Components/ProgressButtons/ProgressButtonItem.js +1 -1
- package/build/dist/UI/Components/ProgressButtons/ProgressButtonItem.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenu.js +4 -1
- package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js +3 -1
- package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceList.js +6 -6
- package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.js +1 -1
- package/build/dist/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentsModal.js +2 -2
- package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/StepTraceViewer.js +1 -1
- package/build/dist/UI/Components/Workflow/StepTraceViewer.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js +66 -33
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js +7 -0
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js.map +1 -1
- package/build/dist/UI/Utils/TelemetryService.js +3 -2
- package/build/dist/UI/Utils/TelemetryService.js.map +1 -1
- package/build/dist/Utils/LabelRuleImportExport.js +2 -0
- package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
- package/build/dist/Utils/MetricUnitUtil.js +77 -13
- package/build/dist/Utils/MetricUnitUtil.js.map +1 -1
- package/build/dist/Utils/Monitor/MetricValueFormatter.js +58 -13
- package/build/dist/Utils/Monitor/MetricValueFormatter.js.map +1 -1
- package/build/dist/Utils/Monitor/PlatformMetricUnitUtil.js +161 -0
- package/build/dist/Utils/Monitor/PlatformMetricUnitUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/PlatformResourceIdentity.js +323 -0
- package/build/dist/Utils/Monitor/PlatformResourceIdentity.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.js +270 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +23 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js +61 -0
- package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js.map +1 -1
- package/build/dist/Utils/Telemetry/DatabaseServerEntityKeys.js +178 -0
- package/build/dist/Utils/Telemetry/DatabaseServerEntityKeys.js.map +1 -0
- package/build/dist/Utils/Telemetry/EntityKey.js +133 -0
- package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
- package/build/dist/Utils/ValueFormatter.js +15 -0
- package/build/dist/Utils/ValueFormatter.js.map +1 -1
- package/package.json +1 -1
- package/tsconfig.tests.json +7 -5
|
@@ -0,0 +1,1005 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FOREIGN_HIDDEN_RULE_CSS,
|
|
3
|
+
LAPTOP_WIDTH_IN_PX,
|
|
4
|
+
PHONE_WIDTH_IN_PX,
|
|
5
|
+
TABLET_WIDTH_IN_PX,
|
|
6
|
+
TAILWIND_BREAKPOINTS_IN_PX,
|
|
7
|
+
WIDE_DESKTOP_WIDTH_IN_PX,
|
|
8
|
+
resolveDisplay,
|
|
9
|
+
splitVariants,
|
|
10
|
+
} from "../ResponsiveVisibility";
|
|
11
|
+
import {
|
|
12
|
+
afterAll,
|
|
13
|
+
beforeAll,
|
|
14
|
+
describe,
|
|
15
|
+
expect,
|
|
16
|
+
jest,
|
|
17
|
+
test,
|
|
18
|
+
} from "@jest/globals";
|
|
19
|
+
import { waitFor } from "@testing-library/react";
|
|
20
|
+
import fs from "fs";
|
|
21
|
+
import path from "path";
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
* The fix for the missing navigation bar swapped every `hidden md:flex` for
|
|
25
|
+
* `max-md:hidden md:flex`. The two only paint the same if Tailwind emits the
|
|
26
|
+
* max-width variant the way we think it does: `display:none` below the
|
|
27
|
+
* breakpoint, nothing from the breakpoint up, in a block the `md:flex` rule
|
|
28
|
+
* still comes after. Nothing else in the suite checks that. Every frontend
|
|
29
|
+
* styles itself at runtime with the Play CDN (index.ejs serves the vendored
|
|
30
|
+
* tailwind-3.4.5.js), so there is no build output to inspect, and jsdom has no
|
|
31
|
+
* stylesheet at all: the suites that guard the navigation read class
|
|
32
|
+
* attributes through ResponsiveVisibility.ts, which carries its own model of
|
|
33
|
+
* Tailwind's cascade.
|
|
34
|
+
*
|
|
35
|
+
* This file holds that model to the real thing. It runs the vendored script in
|
|
36
|
+
* jsdom the way the page does - a classic <script>, then `tailwind.config` as
|
|
37
|
+
* index.ejs sets it - hands it the class strings the fix depends on, and
|
|
38
|
+
* asserts on the CSS the CDN writes. If a Tailwind upgrade moves a media
|
|
39
|
+
* query, reorders the blocks or rewrites an arbitrary-variant selector, this
|
|
40
|
+
* file fails before ResponsiveVisibility.ts starts quietly approving markup a
|
|
41
|
+
* browser would hide.
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
const PLAY_CDN_PATH: string = path.resolve(
|
|
45
|
+
__dirname,
|
|
46
|
+
"..",
|
|
47
|
+
"..",
|
|
48
|
+
"Server",
|
|
49
|
+
"Static",
|
|
50
|
+
"Vendor",
|
|
51
|
+
"tailwind",
|
|
52
|
+
"tailwind-3.4.5.js",
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const FEATURE_SET_ROOT: string = path.resolve(
|
|
56
|
+
__dirname,
|
|
57
|
+
"..",
|
|
58
|
+
"..",
|
|
59
|
+
"..",
|
|
60
|
+
"App",
|
|
61
|
+
"FeatureSet",
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
const DASHBOARD_INDEX_VIEW: string = path.join(
|
|
65
|
+
FEATURE_SET_ROOT,
|
|
66
|
+
"Dashboard",
|
|
67
|
+
"views",
|
|
68
|
+
"index.ejs",
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
// The inline config in the Dashboard's index.ejs (checked below).
|
|
72
|
+
const INDEX_VIEW_TAILWIND_CONFIG: Record<string, unknown> = {
|
|
73
|
+
darkMode: "class",
|
|
74
|
+
theme: {
|
|
75
|
+
extend: {
|
|
76
|
+
fontFamily: {
|
|
77
|
+
display: ["Inter", "sans-serif"],
|
|
78
|
+
body: ["Inter", "sans-serif"],
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const BREAKPOINTS: Array<string> = Object.keys(TAILWIND_BREAKPOINTS_IN_PX);
|
|
85
|
+
|
|
86
|
+
/*
|
|
87
|
+
* The order ResponsiveVisibility.ts ranks display utilities in (its
|
|
88
|
+
* maxVariantPrecedence / minVariantPrecedence). If the CDN stops emitting the
|
|
89
|
+
* blocks in this order, it is the helper that is wrong, not this list.
|
|
90
|
+
*/
|
|
91
|
+
const EMIT_ORDER_ASSUMED_BY_RESPONSIVE_VISIBILITY: Array<string> = [
|
|
92
|
+
"unprefixed",
|
|
93
|
+
"max-2xl",
|
|
94
|
+
"max-xl",
|
|
95
|
+
"max-lg",
|
|
96
|
+
"max-md",
|
|
97
|
+
"max-sm",
|
|
98
|
+
"sm",
|
|
99
|
+
"md",
|
|
100
|
+
"lg",
|
|
101
|
+
"xl",
|
|
102
|
+
"2xl",
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
/*
|
|
106
|
+
* The two class names the facet rows and the runbook execution view moved to,
|
|
107
|
+
* and the selectors Tailwind 3.4.5 is expected to write for them.
|
|
108
|
+
*/
|
|
109
|
+
const GROUP_NOT_HOVER_HIDDEN: string = "group-[:not(:hover)]:hidden";
|
|
110
|
+
const GROUP_NOT_HOVER_HIDDEN_SELECTOR: string =
|
|
111
|
+
".group:not(:hover) .group-\\[\\:not\\(\\:hover\\)\\]\\:hidden";
|
|
112
|
+
const DETAILS_CLOSED_HIDDEN: string = "[details:not([open])>summary>&]:hidden";
|
|
113
|
+
const DETAILS_CLOSED_HIDDEN_SELECTOR: string =
|
|
114
|
+
"details:not([open])>summary>.\\[details\\:not\\(\\[open\\]\\)\\>summary\\>\\&\\]\\:hidden";
|
|
115
|
+
|
|
116
|
+
/*
|
|
117
|
+
* Not every foreign rule is !important. A plain `.hidden{display:none}` in a
|
|
118
|
+
* sheet appended after Tailwind's <style> ties on specificity and wins on
|
|
119
|
+
* source order, which is just as fatal to `hidden md:flex`.
|
|
120
|
+
*/
|
|
121
|
+
const APPENDED_PLAIN_HIDDEN_RULE_CSS: string = ".hidden{display:none}";
|
|
122
|
+
|
|
123
|
+
interface ConvertedClassString {
|
|
124
|
+
where: string;
|
|
125
|
+
before: string;
|
|
126
|
+
after: string;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Real before/after pairs from the fix, at least one per breakpoint.
|
|
130
|
+
const CONVERTED_CLASS_STRINGS: Array<ConvertedClassString> = [
|
|
131
|
+
{
|
|
132
|
+
where: "NavBar desktop row",
|
|
133
|
+
before: "bg-white flex text-center items-center lg:py-2 hidden md:flex",
|
|
134
|
+
after:
|
|
135
|
+
"bg-white flex text-center items-center lg:py-2 max-md:hidden md:flex",
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
where: "Dashboard header search rail",
|
|
139
|
+
before: "hidden items-center gap-2 lg:flex",
|
|
140
|
+
after: "max-lg:hidden items-center gap-2 lg:flex",
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
where: "Home side menu",
|
|
144
|
+
before: "hidden md:block w-56 lg:w-64 flex-shrink-0 mb-10",
|
|
145
|
+
after: "max-md:hidden md:block w-56 lg:w-64 flex-shrink-0 mb-10",
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
where: "Pagination page button",
|
|
149
|
+
before: "hidden sm:flex",
|
|
150
|
+
after: "max-sm:hidden sm:flex",
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
where: "Page header actions",
|
|
154
|
+
before:
|
|
155
|
+
"hidden sm:flex sm:flex-wrap sm:items-center sm:justify-end sm:gap-3",
|
|
156
|
+
after:
|
|
157
|
+
"max-sm:hidden sm:flex sm:flex-wrap sm:items-center sm:justify-end sm:gap-3",
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
where: "Workflow query builder column headings",
|
|
161
|
+
before:
|
|
162
|
+
"hidden border-b border-gray-100 bg-gray-50/60 px-3 py-1.5 text-[10px] font-semibold uppercase tracking-[0.08em] text-gray-400 sm:grid sm:grid-cols-[minmax(0,1fr)_minmax(0,0.85fr)_minmax(0,1.3fr)_auto] sm:gap-2",
|
|
163
|
+
after:
|
|
164
|
+
"max-sm:hidden border-b border-gray-100 bg-gray-50/60 px-3 py-1.5 text-[10px] font-semibold uppercase tracking-[0.08em] text-gray-400 sm:grid sm:grid-cols-[minmax(0,1fr)_minmax(0,0.85fr)_minmax(0,1.3fr)_auto] sm:gap-2",
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
where: "AI insight skeleton column",
|
|
168
|
+
before: "hidden w-36 flex-shrink-0 xl:block",
|
|
169
|
+
after: "max-xl:hidden w-36 flex-shrink-0 xl:block",
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
where: "Session replay timestamp",
|
|
173
|
+
before: "hidden text-gray-400 2xl:inline",
|
|
174
|
+
after: "max-2xl:hidden text-gray-400 2xl:inline",
|
|
175
|
+
},
|
|
176
|
+
];
|
|
177
|
+
|
|
178
|
+
/*
|
|
179
|
+
* Strings whose answer turns on a precedence rule rather than on one
|
|
180
|
+
* breakpoint: max-* over unprefixed, the narrower max-* over the wider, a
|
|
181
|
+
* min-width variant over a max-width one, and the order display utilities
|
|
182
|
+
* keep inside one block (`hidden` last, `grid` after `flex` after `block`).
|
|
183
|
+
*/
|
|
184
|
+
const PRECEDENCE_PROBES: Array<string> = [
|
|
185
|
+
"flex max-lg:hidden",
|
|
186
|
+
"max-xl:hidden max-md:block",
|
|
187
|
+
"max-lg:hidden sm:block",
|
|
188
|
+
"hidden flex",
|
|
189
|
+
"block inline-flex",
|
|
190
|
+
"contents grid inline-block",
|
|
191
|
+
"md:grid md:flex md:block",
|
|
192
|
+
"max-md:hidden md:inline-flex",
|
|
193
|
+
"max-sm:hidden sm:inline-block",
|
|
194
|
+
"max-sm:hidden sm:inline",
|
|
195
|
+
"text-sm font-medium",
|
|
196
|
+
];
|
|
197
|
+
|
|
198
|
+
/*
|
|
199
|
+
* Every display utility Tailwind 3.4.5 has, alphabetically: the order that
|
|
200
|
+
* matters is the one the CDN emits them in, and that is read from its output.
|
|
201
|
+
*/
|
|
202
|
+
const EVERY_DISPLAY_UTILITY: string =
|
|
203
|
+
"block contents flex flow-root grid hidden inline inline-block inline-flex inline-grid inline-table list-item table table-caption table-cell table-column table-column-group table-footer-group table-header-group table-row table-row-group";
|
|
204
|
+
|
|
205
|
+
// Named viewports; every breakpoint edge the CDN emits is added on top.
|
|
206
|
+
const ASSERTED_WIDTHS_IN_PX: Array<number> = [
|
|
207
|
+
PHONE_WIDTH_IN_PX,
|
|
208
|
+
640,
|
|
209
|
+
767,
|
|
210
|
+
TABLET_WIDTH_IN_PX,
|
|
211
|
+
1024,
|
|
212
|
+
LAPTOP_WIDTH_IN_PX,
|
|
213
|
+
WIDE_DESKTOP_WIDTH_IN_PX,
|
|
214
|
+
];
|
|
215
|
+
|
|
216
|
+
interface PlayCdnGlobal {
|
|
217
|
+
config: Record<string, unknown>;
|
|
218
|
+
defaultTheme: { screens: Record<string, string> };
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
interface EmittedRule {
|
|
222
|
+
order: number;
|
|
223
|
+
// Enclosing at-rule preludes, outermost first: "@media (min-width: 640px)".
|
|
224
|
+
atRules: Array<string>;
|
|
225
|
+
selector: string;
|
|
226
|
+
declarations: string;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
interface DisplayDeclaration {
|
|
230
|
+
value: string;
|
|
231
|
+
important: boolean;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function playCdn(): PlayCdnGlobal | undefined {
|
|
235
|
+
return (window as unknown as { tailwind?: PlayCdnGlobal }).tailwind;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// The <style> the CDN appends to <head>, recognised by its license banner.
|
|
239
|
+
function playCdnCss(): string {
|
|
240
|
+
const style: HTMLStyleElement | undefined = Array.from(
|
|
241
|
+
document.head.querySelectorAll("style"),
|
|
242
|
+
).find((element: HTMLStyleElement) => {
|
|
243
|
+
return (element.textContent || "").includes("tailwindcss v");
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
return style?.textContent || "";
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/*
|
|
250
|
+
* A small parser for the stylesheet the CDN writes: comments dropped, quoted
|
|
251
|
+
* strings and backslash escapes kept intact (Tailwind escapes `:`, `[`, `(`
|
|
252
|
+
* and friends in class names), and every style rule recorded with the at-rules
|
|
253
|
+
* around it and its position in the sheet.
|
|
254
|
+
*/
|
|
255
|
+
function parseStylesheet(css: string): Array<EmittedRule> {
|
|
256
|
+
const rules: Array<EmittedRule> = [];
|
|
257
|
+
const atRules: Array<string> = [];
|
|
258
|
+
let selector: string | null = null;
|
|
259
|
+
let buffer: string = "";
|
|
260
|
+
let index: number = 0;
|
|
261
|
+
|
|
262
|
+
while (index < css.length) {
|
|
263
|
+
const character: string = css[index]!;
|
|
264
|
+
|
|
265
|
+
if (character === "\\") {
|
|
266
|
+
buffer += css.slice(index, index + 2);
|
|
267
|
+
index += 2;
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (character === "/" && css[index + 1] === "*") {
|
|
272
|
+
const commentEnd: number = css.indexOf("*/", index + 2);
|
|
273
|
+
index = commentEnd === -1 ? css.length : commentEnd + 2;
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (character === '"' || character === "'") {
|
|
278
|
+
let stringEnd: number = index + 1;
|
|
279
|
+
|
|
280
|
+
while (stringEnd < css.length && css[stringEnd] !== character) {
|
|
281
|
+
stringEnd += css[stringEnd] === "\\" ? 2 : 1;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
buffer += css.slice(index, stringEnd + 1);
|
|
285
|
+
index = stringEnd + 1;
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (character === "{") {
|
|
290
|
+
const prelude: string = buffer.trim();
|
|
291
|
+
|
|
292
|
+
if (prelude.startsWith("@")) {
|
|
293
|
+
atRules.push(prelude);
|
|
294
|
+
} else {
|
|
295
|
+
selector = prelude;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
buffer = "";
|
|
299
|
+
} else if (character === "}") {
|
|
300
|
+
if (selector !== null) {
|
|
301
|
+
rules.push({
|
|
302
|
+
order: rules.length,
|
|
303
|
+
atRules: [...atRules],
|
|
304
|
+
selector: selector,
|
|
305
|
+
declarations: buffer.trim(),
|
|
306
|
+
});
|
|
307
|
+
selector = null;
|
|
308
|
+
} else {
|
|
309
|
+
atRules.pop();
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
buffer = "";
|
|
313
|
+
} else {
|
|
314
|
+
buffer += character;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
index++;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return rules;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const HEX_DIGIT_FIRST: RegExp = /^[0-9a-fA-F]/;
|
|
324
|
+
const LONE_CLASS_SELECTOR: RegExp =
|
|
325
|
+
/^\.((?:\\[0-9a-fA-F]{1,6}\s?|\\[\s\S]|[\w-])+)$/;
|
|
326
|
+
const DISPLAY_DECLARATION: RegExp =
|
|
327
|
+
/(?:^|;)\s*display\s*:\s*([^;!]+?)\s*(!\s*important)?\s*(?:;|$)/;
|
|
328
|
+
const TAILWIND_CONFIG_ASSIGNMENT: RegExp =
|
|
329
|
+
/tailwind\.config\s*=\s*([\s\S]*?)<\/script>/;
|
|
330
|
+
|
|
331
|
+
// `\:` -> `:`, `\32xl` -> `2xl`, `\2c ` -> `,` (CSS identifier escapes).
|
|
332
|
+
function unescapeCssIdentifier(escaped: string): string {
|
|
333
|
+
return escaped.replace(
|
|
334
|
+
/\\([0-9a-fA-F]{1,6}\s?|[\s\S])/g,
|
|
335
|
+
(_escape: string, sequence: string): string => {
|
|
336
|
+
if (HEX_DIGIT_FIRST.test(sequence)) {
|
|
337
|
+
return String.fromCodePoint(parseInt(sequence.trim(), 16));
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return sequence;
|
|
341
|
+
},
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/*
|
|
346
|
+
* The class name when the selector is one lone class (`.max-md\:hidden`,
|
|
347
|
+
* `.\32xl\:flex`) and null otherwise. Lone-class rules are the ones
|
|
348
|
+
* ResponsiveVisibility.ts models, and they all share one specificity, so
|
|
349
|
+
* source order alone decides between them.
|
|
350
|
+
*/
|
|
351
|
+
function loneClassName(selector: string): string | null {
|
|
352
|
+
const match: RegExpExecArray | null = LONE_CLASS_SELECTOR.exec(selector);
|
|
353
|
+
|
|
354
|
+
return match ? unescapeCssIdentifier(match[1]!) : null;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function displayDeclaration(declarations: string): DisplayDeclaration | null {
|
|
358
|
+
const match: RegExpExecArray | null = DISPLAY_DECLARATION.exec(declarations);
|
|
359
|
+
|
|
360
|
+
if (!match) {
|
|
361
|
+
return null;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return { value: match[1]!, important: Boolean(match[2]) };
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const MIN_WIDTH_MEDIA: RegExp = /^@media \(min-width: (\d+)px\)$/;
|
|
368
|
+
const BELOW_WIDTH_MEDIA: RegExp = /^@media not all and \(min-width: (\d+)px\)$/;
|
|
369
|
+
|
|
370
|
+
/*
|
|
371
|
+
* Whether a rule's media applies at a viewport width, read from the px in the
|
|
372
|
+
* emitted query rather than from the helper's breakpoint table. Anything but
|
|
373
|
+
* the two forms ResponsiveVisibility.ts models is an error, not a guess.
|
|
374
|
+
*/
|
|
375
|
+
function appliesAtWidth(rule: EmittedRule, viewportWidthInPx: number): boolean {
|
|
376
|
+
if (rule.atRules.length === 0) {
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
if (rule.atRules.length === 1) {
|
|
381
|
+
const minWidth: RegExpExecArray | null = MIN_WIDTH_MEDIA.exec(
|
|
382
|
+
rule.atRules[0]!,
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
if (minWidth) {
|
|
386
|
+
return viewportWidthInPx >= Number(minWidth[1]);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const belowWidth: RegExpExecArray | null = BELOW_WIDTH_MEDIA.exec(
|
|
390
|
+
rule.atRules[0]!,
|
|
391
|
+
);
|
|
392
|
+
|
|
393
|
+
if (belowWidth) {
|
|
394
|
+
return viewportWidthInPx < Number(belowWidth[1]);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
throw new Error(
|
|
399
|
+
`${rule.selector} is emitted inside ${JSON.stringify(
|
|
400
|
+
rule.atRules,
|
|
401
|
+
)}; ResponsiveVisibility.ts only models "(min-width: Npx)" and "not all and (min-width: Npx)", so it needs updating for this Tailwind output`,
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/*
|
|
406
|
+
* The display a browser would compute from these rules for an element carrying
|
|
407
|
+
* `classAttribute`: the last applicable declaration wins, unless an earlier
|
|
408
|
+
* one is !important and it is not. Returned in utility terms (`none` reads as
|
|
409
|
+
* `hidden`) so it compares directly with resolveDisplay.
|
|
410
|
+
*/
|
|
411
|
+
function cascadeDisplay(
|
|
412
|
+
rules: Array<EmittedRule>,
|
|
413
|
+
classAttribute: string,
|
|
414
|
+
viewportWidthInPx: number,
|
|
415
|
+
): string | null {
|
|
416
|
+
const tokens: Set<string> = new Set(
|
|
417
|
+
classAttribute.split(/\s+/).filter(Boolean),
|
|
418
|
+
);
|
|
419
|
+
let winner: DisplayDeclaration | null = null;
|
|
420
|
+
|
|
421
|
+
for (const rule of rules) {
|
|
422
|
+
const className: string | null = loneClassName(rule.selector);
|
|
423
|
+
|
|
424
|
+
if (className === null || !tokens.has(className)) {
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const display: DisplayDeclaration | null = displayDeclaration(
|
|
429
|
+
rule.declarations,
|
|
430
|
+
);
|
|
431
|
+
|
|
432
|
+
if (!display || !appliesAtWidth(rule, viewportWidthInPx)) {
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (!winner || display.important || !winner.important) {
|
|
437
|
+
winner = display;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
if (!winner) {
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return winner.value === "none" ? "hidden" : winner.value;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// The object literal assigned to `tailwind.config` in an index.ejs, if any.
|
|
449
|
+
function tailwindConfigSource(indexView: string): string | null {
|
|
450
|
+
const match: RegExpExecArray | null =
|
|
451
|
+
TAILWIND_CONFIG_ASSIGNMENT.exec(indexView);
|
|
452
|
+
|
|
453
|
+
return match ? match[1]! : null;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/*
|
|
457
|
+
* Whitespace, quotes and trailing commas stripped, so an object literal in
|
|
458
|
+
* index.ejs and JSON.stringify of the same object compare equal.
|
|
459
|
+
*/
|
|
460
|
+
function normalizeObjectLiteral(source: string): string {
|
|
461
|
+
return source
|
|
462
|
+
.replace(/[\s'"]/g, "")
|
|
463
|
+
.replace(/;$/, "")
|
|
464
|
+
.replace(/,([}\]])/g, "$1");
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
function rulesForClass(
|
|
468
|
+
rules: Array<EmittedRule>,
|
|
469
|
+
className: string,
|
|
470
|
+
): Array<EmittedRule> {
|
|
471
|
+
return rules.filter((rule: EmittedRule) => {
|
|
472
|
+
return loneClassName(rule.selector) === className;
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
function rulesForSelector(
|
|
477
|
+
rules: Array<EmittedRule>,
|
|
478
|
+
selector: string,
|
|
479
|
+
): Array<EmittedRule> {
|
|
480
|
+
return rules.filter((rule: EmittedRule) => {
|
|
481
|
+
return rule.selector === selector;
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
function everyFixtureClassString(): Array<string> {
|
|
486
|
+
return [
|
|
487
|
+
...CONVERTED_CLASS_STRINGS.flatMap((pair: ConvertedClassString) => {
|
|
488
|
+
return [pair.before, pair.after];
|
|
489
|
+
}),
|
|
490
|
+
...PRECEDENCE_PROBES,
|
|
491
|
+
EVERY_DISPLAY_UTILITY,
|
|
492
|
+
...BREAKPOINTS.map((breakpoint: string) => {
|
|
493
|
+
return `max-${breakpoint}:hidden ${breakpoint}:flex`;
|
|
494
|
+
}),
|
|
495
|
+
];
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/*
|
|
499
|
+
* The CDN keeps two MutationObservers on the document for the life of the page
|
|
500
|
+
* and exposes neither. jsdom empties the document when the file finishes, the
|
|
501
|
+
* observers fire into a window that no longer has one, and the worker dies on
|
|
502
|
+
* a TypeError. Recording them as they are built lets afterAll disconnect them.
|
|
503
|
+
*/
|
|
504
|
+
const OriginalMutationObserver: typeof MutationObserver =
|
|
505
|
+
window.MutationObserver;
|
|
506
|
+
const playCdnObservers: Array<MutationObserver> = [];
|
|
507
|
+
|
|
508
|
+
class RecordingMutationObserver extends OriginalMutationObserver {
|
|
509
|
+
public constructor(callback: MutationCallback) {
|
|
510
|
+
super(callback);
|
|
511
|
+
playCdnObservers.push(this);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// Carried by the fixture container only, so its rule marks the fixture build.
|
|
516
|
+
const FIXTURE_SENTINEL_CLASS: string = "isolate";
|
|
517
|
+
|
|
518
|
+
let emittedCss: string = "";
|
|
519
|
+
let emittedRules: Array<EmittedRule> = [];
|
|
520
|
+
let detailsFixture: HTMLDetailsElement;
|
|
521
|
+
let detailsFixtureLabel: HTMLSpanElement;
|
|
522
|
+
|
|
523
|
+
beforeAll(async () => {
|
|
524
|
+
window.MutationObserver = RecordingMutationObserver;
|
|
525
|
+
|
|
526
|
+
// The CDN announces itself on console.warn; that is noise here, not news.
|
|
527
|
+
const warn: ReturnType<typeof jest.spyOn> = jest
|
|
528
|
+
.spyOn(console, "warn")
|
|
529
|
+
.mockImplementation(() => {});
|
|
530
|
+
|
|
531
|
+
const script: HTMLScriptElement = document.createElement("script");
|
|
532
|
+
script.textContent = fs.readFileSync(PLAY_CDN_PATH, "utf-8");
|
|
533
|
+
document.head.appendChild(script);
|
|
534
|
+
|
|
535
|
+
warn.mockRestore();
|
|
536
|
+
|
|
537
|
+
const cdn: PlayCdnGlobal | undefined = playCdn();
|
|
538
|
+
|
|
539
|
+
if (!cdn) {
|
|
540
|
+
throw new Error(
|
|
541
|
+
"the vendored Play CDN did not run: jest-environment-jsdom must execute <script> elements (runScripts: 'dangerously')",
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
cdn.config = INDEX_VIEW_TAILWIND_CONFIG;
|
|
546
|
+
|
|
547
|
+
/*
|
|
548
|
+
* Setting the config starts a full build. Let it land before adding the
|
|
549
|
+
* fixture, so it cannot finish late and overwrite the build that follows.
|
|
550
|
+
*/
|
|
551
|
+
await waitFor(
|
|
552
|
+
() => {
|
|
553
|
+
expect(playCdnCss()).not.toBe("");
|
|
554
|
+
},
|
|
555
|
+
{ timeout: 30000 },
|
|
556
|
+
);
|
|
557
|
+
|
|
558
|
+
const fixture: HTMLDivElement = document.createElement("div");
|
|
559
|
+
fixture.className = FIXTURE_SENTINEL_CLASS;
|
|
560
|
+
|
|
561
|
+
for (const classAttribute of everyFixtureClassString()) {
|
|
562
|
+
const element: HTMLDivElement = document.createElement("div");
|
|
563
|
+
element.className = classAttribute;
|
|
564
|
+
fixture.appendChild(element);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// The facet row's remove button, inside its `group` row.
|
|
568
|
+
const facetRow: HTMLDivElement = document.createElement("div");
|
|
569
|
+
facetRow.className = "group flex";
|
|
570
|
+
const removeButton: HTMLButtonElement = document.createElement("button");
|
|
571
|
+
removeButton.className = `flex h-5 w-5 items-center ${GROUP_NOT_HOVER_HIDDEN}`;
|
|
572
|
+
facetRow.appendChild(removeButton);
|
|
573
|
+
fixture.appendChild(facetRow);
|
|
574
|
+
|
|
575
|
+
// The runbook step label, in the details > summary > span shape it ships in.
|
|
576
|
+
detailsFixture = document.createElement("details");
|
|
577
|
+
const summary: HTMLElement = document.createElement("summary");
|
|
578
|
+
detailsFixtureLabel = document.createElement("span");
|
|
579
|
+
detailsFixtureLabel.className = `inline ${DETAILS_CLOSED_HIDDEN}`;
|
|
580
|
+
summary.appendChild(detailsFixtureLabel);
|
|
581
|
+
detailsFixture.appendChild(summary);
|
|
582
|
+
fixture.appendChild(detailsFixture);
|
|
583
|
+
|
|
584
|
+
document.body.appendChild(fixture);
|
|
585
|
+
|
|
586
|
+
/*
|
|
587
|
+
* The fixture goes in with one append and the CDN collects every class in
|
|
588
|
+
* the document in one pass, so once the container's own class is in the
|
|
589
|
+
* sheet the rest of the fixture is too. Waiting on that, not on the rules
|
|
590
|
+
* under test, lets a changed rule fail its own test with its own message.
|
|
591
|
+
*/
|
|
592
|
+
await waitFor(
|
|
593
|
+
() => {
|
|
594
|
+
expect(
|
|
595
|
+
rulesForClass(parseStylesheet(playCdnCss()), FIXTURE_SENTINEL_CLASS),
|
|
596
|
+
).toHaveLength(1);
|
|
597
|
+
},
|
|
598
|
+
{ timeout: 30000 },
|
|
599
|
+
);
|
|
600
|
+
|
|
601
|
+
emittedCss = playCdnCss();
|
|
602
|
+
emittedRules = parseStylesheet(emittedCss);
|
|
603
|
+
}, 60000);
|
|
604
|
+
|
|
605
|
+
afterAll(() => {
|
|
606
|
+
for (const observer of playCdnObservers) {
|
|
607
|
+
observer.disconnect();
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
window.MutationObserver = OriginalMutationObserver;
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
describe("vendored Tailwind Play CDN output", () => {
|
|
614
|
+
test("is the 3.4.5 build, and its screens are the breakpoints ResponsiveVisibility.ts assumes", () => {
|
|
615
|
+
expect(emittedCss).toContain("tailwindcss v3.4.5");
|
|
616
|
+
|
|
617
|
+
const expectedScreens: Record<string, string> = {};
|
|
618
|
+
|
|
619
|
+
for (const breakpoint of BREAKPOINTS) {
|
|
620
|
+
expectedScreens[breakpoint] =
|
|
621
|
+
`${TAILWIND_BREAKPOINTS_IN_PX[breakpoint]}px`;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
expect(playCdn()!.defaultTheme.screens).toEqual(expectedScreens);
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
test("is configured here exactly as the Dashboard's index.ejs configures it", () => {
|
|
628
|
+
const source: string | null = tailwindConfigSource(
|
|
629
|
+
fs.readFileSync(DASHBOARD_INDEX_VIEW, "utf8"),
|
|
630
|
+
);
|
|
631
|
+
|
|
632
|
+
expect(source).not.toBeNull();
|
|
633
|
+
expect(normalizeObjectLiteral(source!)).toBe(
|
|
634
|
+
normalizeObjectLiteral(JSON.stringify(INDEX_VIEW_TAILWIND_CONFIG)),
|
|
635
|
+
);
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
test("no frontend that loads it redefines the screens", () => {
|
|
639
|
+
/*
|
|
640
|
+
* A `screens` entry would move the breakpoints the helper and this file
|
|
641
|
+
* assume, and Tailwind 3 only generates max-* variants while every screen
|
|
642
|
+
* is a plain min-width - a customised one can make them vanish, and the
|
|
643
|
+
* fix with them.
|
|
644
|
+
*/
|
|
645
|
+
const viewsLoadingTheCdn: Array<string> = [];
|
|
646
|
+
const viewsRedefiningScreens: Array<string> = [];
|
|
647
|
+
|
|
648
|
+
for (const featureSet of fs.readdirSync(FEATURE_SET_ROOT)) {
|
|
649
|
+
const indexViewPath: string = path.join(
|
|
650
|
+
FEATURE_SET_ROOT,
|
|
651
|
+
featureSet,
|
|
652
|
+
"views",
|
|
653
|
+
"index.ejs",
|
|
654
|
+
);
|
|
655
|
+
|
|
656
|
+
if (!fs.existsSync(indexViewPath)) {
|
|
657
|
+
continue;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
const indexView: string = fs.readFileSync(indexViewPath, "utf8");
|
|
661
|
+
|
|
662
|
+
if (!indexView.includes("tailwind-3.4.5.js")) {
|
|
663
|
+
continue;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
viewsLoadingTheCdn.push(featureSet);
|
|
667
|
+
|
|
668
|
+
if ((tailwindConfigSource(indexView) || "").includes("screens")) {
|
|
669
|
+
viewsRedefiningScreens.push(featureSet);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
expect(viewsLoadingTheCdn).toEqual(
|
|
674
|
+
expect.arrayContaining([
|
|
675
|
+
"Accounts",
|
|
676
|
+
"AdminDashboard",
|
|
677
|
+
"Dashboard",
|
|
678
|
+
"PublicDashboard",
|
|
679
|
+
"StatusPage",
|
|
680
|
+
]),
|
|
681
|
+
);
|
|
682
|
+
expect(viewsRedefiningScreens).toEqual([]);
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
test.each(BREAKPOINTS)(
|
|
686
|
+
"max-%s:hidden is display:none below the breakpoint and nothing from it up",
|
|
687
|
+
(breakpoint: string) => {
|
|
688
|
+
const rules: Array<EmittedRule> = rulesForClass(
|
|
689
|
+
emittedRules,
|
|
690
|
+
`max-${breakpoint}:hidden`,
|
|
691
|
+
);
|
|
692
|
+
|
|
693
|
+
expect(
|
|
694
|
+
rules.map((rule: EmittedRule) => {
|
|
695
|
+
return { atRules: rule.atRules, declarations: rule.declarations };
|
|
696
|
+
}),
|
|
697
|
+
).toEqual([
|
|
698
|
+
{
|
|
699
|
+
atRules: [
|
|
700
|
+
`@media not all and (min-width: ${TAILWIND_BREAKPOINTS_IN_PX[breakpoint]}px)`,
|
|
701
|
+
],
|
|
702
|
+
declarations: "display:none",
|
|
703
|
+
},
|
|
704
|
+
]);
|
|
705
|
+
},
|
|
706
|
+
);
|
|
707
|
+
|
|
708
|
+
test.each(BREAKPOINTS)(
|
|
709
|
+
"%s:flex, the counterpart that shows the element again, applies from the breakpoint up",
|
|
710
|
+
(breakpoint: string) => {
|
|
711
|
+
const rules: Array<EmittedRule> = rulesForClass(
|
|
712
|
+
emittedRules,
|
|
713
|
+
`${breakpoint}:flex`,
|
|
714
|
+
);
|
|
715
|
+
|
|
716
|
+
expect(
|
|
717
|
+
rules.map((rule: EmittedRule) => {
|
|
718
|
+
return { atRules: rule.atRules, declarations: rule.declarations };
|
|
719
|
+
}),
|
|
720
|
+
).toEqual([
|
|
721
|
+
{
|
|
722
|
+
atRules: [
|
|
723
|
+
`@media (min-width: ${TAILWIND_BREAKPOINTS_IN_PX[breakpoint]}px)`,
|
|
724
|
+
],
|
|
725
|
+
declarations: "display:flex",
|
|
726
|
+
},
|
|
727
|
+
]);
|
|
728
|
+
},
|
|
729
|
+
);
|
|
730
|
+
|
|
731
|
+
test("every responsive display rule sits in the media query its variant names", () => {
|
|
732
|
+
const misplaced: Array<string> = [];
|
|
733
|
+
let responsiveDisplayRules: number = 0;
|
|
734
|
+
|
|
735
|
+
for (const rule of emittedRules) {
|
|
736
|
+
const className: string | null = loneClassName(rule.selector);
|
|
737
|
+
|
|
738
|
+
if (className === null || !displayDeclaration(rule.declarations)) {
|
|
739
|
+
continue;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
const parts: Array<string> = splitVariants(className);
|
|
743
|
+
|
|
744
|
+
if (parts.length !== 2) {
|
|
745
|
+
continue;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
const variant: string = parts[0]!;
|
|
749
|
+
const isMaxVariant: boolean = variant.startsWith("max-");
|
|
750
|
+
const breakpoint: string = isMaxVariant ? variant.slice(4) : variant;
|
|
751
|
+
const breakpointInPx: number | undefined =
|
|
752
|
+
TAILWIND_BREAKPOINTS_IN_PX[breakpoint];
|
|
753
|
+
|
|
754
|
+
if (breakpointInPx === undefined) {
|
|
755
|
+
continue;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
responsiveDisplayRules++;
|
|
759
|
+
|
|
760
|
+
const expectedMedia: string = isMaxVariant
|
|
761
|
+
? `@media not all and (min-width: ${breakpointInPx}px)`
|
|
762
|
+
: `@media (min-width: ${breakpointInPx}px)`;
|
|
763
|
+
|
|
764
|
+
if (rule.atRules.length !== 1 || rule.atRules[0] !== expectedMedia) {
|
|
765
|
+
misplaced.push(`${rule.selector} in ${JSON.stringify(rule.atRules)}`);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
expect(misplaced).toEqual([]);
|
|
770
|
+
// sm..2xl in both directions at the very least, so the loop did look.
|
|
771
|
+
expect(responsiveDisplayRules).toBeGreaterThanOrEqual(
|
|
772
|
+
2 * BREAKPOINTS.length,
|
|
773
|
+
);
|
|
774
|
+
});
|
|
775
|
+
|
|
776
|
+
test("display blocks come out in the order ResponsiveVisibility.ts ranks them", () => {
|
|
777
|
+
/*
|
|
778
|
+
* Every lone-class display rule, labelled with its variant, in sheet
|
|
779
|
+
* order, with runs of the same label collapsed. A block that is split up
|
|
780
|
+
* or out of place shows up as a repeated or misplaced label.
|
|
781
|
+
*/
|
|
782
|
+
const emittedOrder: Array<string> = [];
|
|
783
|
+
|
|
784
|
+
for (const rule of emittedRules) {
|
|
785
|
+
const className: string | null = loneClassName(rule.selector);
|
|
786
|
+
|
|
787
|
+
if (className === null || !displayDeclaration(rule.declarations)) {
|
|
788
|
+
continue;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
const parts: Array<string> = splitVariants(className);
|
|
792
|
+
const group: string = parts.length === 1 ? "unprefixed" : parts[0]!;
|
|
793
|
+
|
|
794
|
+
if (emittedOrder[emittedOrder.length - 1] !== group) {
|
|
795
|
+
emittedOrder.push(group);
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
expect(emittedOrder).toEqual(EMIT_ORDER_ASSUMED_BY_RESPONSIVE_VISIBILITY);
|
|
800
|
+
});
|
|
801
|
+
|
|
802
|
+
test("inside a block, the display utility emitted later is the one ResponsiveVisibility.ts lets win", () => {
|
|
803
|
+
const everyDisplayUtility: Array<string> = EVERY_DISPLAY_UTILITY.split(" ");
|
|
804
|
+
const emittedDisplayOrder: Array<string> = emittedRules
|
|
805
|
+
.map((rule: EmittedRule) => {
|
|
806
|
+
return loneClassName(rule.selector);
|
|
807
|
+
})
|
|
808
|
+
.filter((className: string | null): className is string => {
|
|
809
|
+
return className !== null && everyDisplayUtility.includes(className);
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
expect([...emittedDisplayOrder].sort()).toEqual(
|
|
813
|
+
[...everyDisplayUtility].sort(),
|
|
814
|
+
);
|
|
815
|
+
|
|
816
|
+
/*
|
|
817
|
+
* Adjacent pairs are enough: the model ranks utilities on one list, so
|
|
818
|
+
* agreeing on every neighbour means agreeing on the whole order.
|
|
819
|
+
*/
|
|
820
|
+
const disagreements: Array<string> = [];
|
|
821
|
+
|
|
822
|
+
for (let index: number = 1; index < emittedDisplayOrder.length; index++) {
|
|
823
|
+
const earlier: string = emittedDisplayOrder[index - 1]!;
|
|
824
|
+
const later: string = emittedDisplayOrder[index]!;
|
|
825
|
+
const modelWinner: string | null = resolveDisplay(
|
|
826
|
+
`${later} ${earlier}`,
|
|
827
|
+
LAPTOP_WIDTH_IN_PX,
|
|
828
|
+
);
|
|
829
|
+
|
|
830
|
+
if (modelWinner !== later) {
|
|
831
|
+
disagreements.push(
|
|
832
|
+
`${earlier} is emitted before ${later}, but the model picks ${modelWinner}`,
|
|
833
|
+
);
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
expect(disagreements).toEqual([]);
|
|
838
|
+
});
|
|
839
|
+
|
|
840
|
+
test("group-[:not(:hover)]:hidden emits the selector the facet rows rely on", () => {
|
|
841
|
+
const rules: Array<EmittedRule> = rulesForSelector(
|
|
842
|
+
emittedRules,
|
|
843
|
+
GROUP_NOT_HOVER_HIDDEN_SELECTOR,
|
|
844
|
+
);
|
|
845
|
+
|
|
846
|
+
expect(rules).toHaveLength(1);
|
|
847
|
+
expect(rules[0]!.atRules).toEqual([]);
|
|
848
|
+
expect(rules[0]!.declarations).toBe("display:none");
|
|
849
|
+
|
|
850
|
+
/*
|
|
851
|
+
* It has to beat the unprefixed `flex` on the same button. It outranks it
|
|
852
|
+
* on specificity and it also comes later, so it wins either way.
|
|
853
|
+
*/
|
|
854
|
+
const flex: EmittedRule = rulesForClass(emittedRules, "flex")[0]!;
|
|
855
|
+
expect(rules[0]!.order).toBeGreaterThan(flex.order);
|
|
856
|
+
});
|
|
857
|
+
|
|
858
|
+
test("[details:not([open])>summary>&]:hidden emits the selector the runbook view relies on, and it lets go of an open <details>", () => {
|
|
859
|
+
const rules: Array<EmittedRule> = rulesForSelector(
|
|
860
|
+
emittedRules,
|
|
861
|
+
DETAILS_CLOSED_HIDDEN_SELECTOR,
|
|
862
|
+
);
|
|
863
|
+
|
|
864
|
+
expect(rules).toHaveLength(1);
|
|
865
|
+
expect(rules[0]!.atRules).toEqual([]);
|
|
866
|
+
expect(rules[0]!.declarations).toBe("display:none");
|
|
867
|
+
|
|
868
|
+
const inline: EmittedRule = rulesForClass(emittedRules, "inline")[0]!;
|
|
869
|
+
expect(rules[0]!.order).toBeGreaterThan(inline.order);
|
|
870
|
+
|
|
871
|
+
// `&` became the element's own class, so it selects the label itself ...
|
|
872
|
+
expect(detailsFixtureLabel.matches(rules[0]!.selector)).toBe(true);
|
|
873
|
+
|
|
874
|
+
// ... and only while the disclosure is closed.
|
|
875
|
+
detailsFixture.open = true;
|
|
876
|
+
|
|
877
|
+
try {
|
|
878
|
+
expect(detailsFixtureLabel.matches(rules[0]!.selector)).toBe(false);
|
|
879
|
+
} finally {
|
|
880
|
+
detailsFixture.open = false;
|
|
881
|
+
}
|
|
882
|
+
});
|
|
883
|
+
});
|
|
884
|
+
|
|
885
|
+
describe("the emitted cascade agrees with resolveDisplay", () => {
|
|
886
|
+
/*
|
|
887
|
+
* Each breakpoint's last hidden pixel and first shown pixel, read from the
|
|
888
|
+
* media queries the CDN actually wrote, on top of the named viewports.
|
|
889
|
+
*/
|
|
890
|
+
function widthsToCheck(): Array<number> {
|
|
891
|
+
const widths: Set<number> = new Set(ASSERTED_WIDTHS_IN_PX);
|
|
892
|
+
|
|
893
|
+
for (const rule of emittedRules) {
|
|
894
|
+
for (const atRule of rule.atRules) {
|
|
895
|
+
const media: RegExpExecArray | null =
|
|
896
|
+
MIN_WIDTH_MEDIA.exec(atRule) || BELOW_WIDTH_MEDIA.exec(atRule);
|
|
897
|
+
|
|
898
|
+
if (media) {
|
|
899
|
+
widths.add(Number(media[1]) - 1);
|
|
900
|
+
widths.add(Number(media[1]));
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
return Array.from(widths).sort((left: number, right: number) => {
|
|
906
|
+
return left - right;
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
function cascadeAcrossWidths(
|
|
911
|
+
rules: Array<EmittedRule>,
|
|
912
|
+
classAttribute: string,
|
|
913
|
+
): Array<string> {
|
|
914
|
+
return widthsToCheck().map((width: number) => {
|
|
915
|
+
return `${width}px: ${cascadeDisplay(rules, classAttribute, width)}`;
|
|
916
|
+
});
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
function modelAcrossWidths(
|
|
920
|
+
classAttribute: string,
|
|
921
|
+
withForeignHiddenRule: boolean,
|
|
922
|
+
): Array<string> {
|
|
923
|
+
return widthsToCheck().map((width: number) => {
|
|
924
|
+
return `${width}px: ${resolveDisplay(classAttribute, width, {
|
|
925
|
+
withForeignHiddenRule,
|
|
926
|
+
})}`;
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
test("the widths checked include every breakpoint edge", () => {
|
|
931
|
+
const widths: Array<number> = widthsToCheck();
|
|
932
|
+
|
|
933
|
+
for (const breakpoint of BREAKPOINTS) {
|
|
934
|
+
const breakpointInPx: number = TAILWIND_BREAKPOINTS_IN_PX[breakpoint]!;
|
|
935
|
+
expect(widths).toEqual(
|
|
936
|
+
expect.arrayContaining([breakpointInPx - 1, breakpointInPx]),
|
|
937
|
+
);
|
|
938
|
+
}
|
|
939
|
+
});
|
|
940
|
+
|
|
941
|
+
test.each(everyFixtureClassString())(
|
|
942
|
+
'"%s" resolves the same from the real CSS as from the model, with and without a foreign .hidden rule',
|
|
943
|
+
(classAttribute: string) => {
|
|
944
|
+
expect(cascadeAcrossWidths(emittedRules, classAttribute)).toEqual(
|
|
945
|
+
modelAcrossWidths(classAttribute, false),
|
|
946
|
+
);
|
|
947
|
+
|
|
948
|
+
// Appended after Tailwind's <style>, as an extension or user sheet is.
|
|
949
|
+
for (const foreignCss of [
|
|
950
|
+
FOREIGN_HIDDEN_RULE_CSS,
|
|
951
|
+
APPENDED_PLAIN_HIDDEN_RULE_CSS,
|
|
952
|
+
]) {
|
|
953
|
+
expect(
|
|
954
|
+
cascadeAcrossWidths(
|
|
955
|
+
parseStylesheet(emittedCss + foreignCss),
|
|
956
|
+
classAttribute,
|
|
957
|
+
),
|
|
958
|
+
).toEqual(modelAcrossWidths(classAttribute, true));
|
|
959
|
+
}
|
|
960
|
+
},
|
|
961
|
+
);
|
|
962
|
+
|
|
963
|
+
test.each(CONVERTED_CLASS_STRINGS)(
|
|
964
|
+
"$where: the new classes paint exactly as the old ones did, and a foreign .hidden rule no longer removes them",
|
|
965
|
+
({ before, after }: ConvertedClassString) => {
|
|
966
|
+
// Display-equivalent at every width, by the real stylesheet.
|
|
967
|
+
expect(cascadeAcrossWidths(emittedRules, after)).toEqual(
|
|
968
|
+
cascadeAcrossWidths(emittedRules, before),
|
|
969
|
+
);
|
|
970
|
+
|
|
971
|
+
for (const foreignCss of [
|
|
972
|
+
FOREIGN_HIDDEN_RULE_CSS,
|
|
973
|
+
APPENDED_PLAIN_HIDDEN_RULE_CSS,
|
|
974
|
+
]) {
|
|
975
|
+
const withForeignRule: Array<EmittedRule> = parseStylesheet(
|
|
976
|
+
emittedCss + foreignCss,
|
|
977
|
+
);
|
|
978
|
+
|
|
979
|
+
// Immune: the foreign rule changes nothing for the new classes ...
|
|
980
|
+
expect(cascadeAcrossWidths(withForeignRule, after)).toEqual(
|
|
981
|
+
cascadeAcrossWidths(emittedRules, after),
|
|
982
|
+
);
|
|
983
|
+
|
|
984
|
+
/*
|
|
985
|
+
* ... while the same check fails for the old ones. At the customer's
|
|
986
|
+
* 1917px the old classes were on screen and the foreign rule took
|
|
987
|
+
* them off it - the missing navigation bar, reproduced from the real
|
|
988
|
+
* CSS.
|
|
989
|
+
*/
|
|
990
|
+
expect(cascadeAcrossWidths(withForeignRule, before)).not.toEqual(
|
|
991
|
+
cascadeAcrossWidths(emittedRules, before),
|
|
992
|
+
);
|
|
993
|
+
expect(
|
|
994
|
+
cascadeDisplay(emittedRules, before, WIDE_DESKTOP_WIDTH_IN_PX),
|
|
995
|
+
).not.toBe("hidden");
|
|
996
|
+
expect(
|
|
997
|
+
cascadeDisplay(withForeignRule, before, WIDE_DESKTOP_WIDTH_IN_PX),
|
|
998
|
+
).toBe("hidden");
|
|
999
|
+
expect(
|
|
1000
|
+
cascadeDisplay(withForeignRule, after, WIDE_DESKTOP_WIDTH_IN_PX),
|
|
1001
|
+
).not.toBe("hidden");
|
|
1002
|
+
}
|
|
1003
|
+
},
|
|
1004
|
+
);
|
|
1005
|
+
});
|