Alerting: Add eslint testing-library plugin dependency and create separate ESLint config (#91052)

pull/90094/head
Tom Ratcliffe 11 months ago committed by GitHub
parent e3842df675
commit 6fcf594b32
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 13
      .eslintrc
  2. 1
      package.json
  3. 9
      public/app/features/alerting/.eslintrc
  4. 54
      public/app/features/alerting/unified/CloneRuleEditor.test.tsx
  5. 13
      public/app/features/alerting/unified/GrafanaRuleQueryViewer.test.tsx
  6. 2
      public/app/features/alerting/unified/RuleEditorCloudOnlyAllowed.test.tsx
  7. 4
      public/app/features/alerting/unified/RuleEditorCloudRules.test.tsx
  8. 2
      public/app/features/alerting/unified/RuleEditorGrafanaRules.test.tsx
  9. 2
      public/app/features/alerting/unified/RuleEditorRecordingRule.test.tsx
  10. 3
      public/app/features/alerting/unified/RuleList.test.tsx
  11. 6
      public/app/features/alerting/unified/Settings.test.tsx
  12. 27
      public/app/features/alerting/unified/components/contact-points/ContactPoints.test.tsx
  13. 14
      public/app/features/alerting/unified/components/mute-timings/MuteTimingsTable.test.tsx
  14. 23
      public/app/features/alerting/unified/components/receivers/TemplatePreview.test.tsx
  15. 5
      public/app/features/alerting/unified/components/receivers/form/GrafanaReceiverForm.test.tsx
  16. 38
      public/app/features/alerting/unified/components/rule-editor/AnnotationsStep.test.tsx
  17. 18
      public/app/features/alerting/unified/components/rule-editor/DashboardPicker.test.tsx
  18. 4
      public/app/features/alerting/unified/components/rule-editor/EvaluationGroupQuickPick.test.tsx
  19. 4
      public/app/features/alerting/unified/components/rule-editor/PendingPeriodQuickPick.test.tsx
  20. 4
      public/app/features/alerting/unified/components/rule-editor/alert-rule-form/simplifiedRouting/SimplifiedRuleEditor.test.tsx
  21. 10
      public/app/features/alerting/unified/components/rule-editor/notificaton-preview/NotificationPreview.test.tsx
  22. 6
      public/app/features/alerting/unified/components/rule-viewer/RuleViewer.test.tsx
  23. 6
      public/app/features/alerting/unified/components/rules/state-history/LogRecordViewer.test.tsx
  24. 44
      public/app/features/alerting/unified/hooks/useAbilities.test.tsx
  25. 44
      public/app/features/alerting/unified/hooks/useExternalAMSelector.test.tsx
  26. 263
      yarn.lock

@ -1,7 +1,18 @@
{
"extends": ["@grafana/eslint-config", "plugin:react/jsx-runtime"],
"root": true,
"plugins": ["@emotion", "lodash", "jest", "import", "jsx-a11y", "@grafana", "no-barrel-files"],
"plugins": [
"@emotion",
"lodash",
"jest",
"import",
"jsx-a11y",
"@grafana",
"no-barrel-files",
// Included so betterer doesn't fail when processing all files,
// as other parts of the code use testing-library plugin
"testing-library",
],
"settings": {
"import/internal-regex": "^(app/)|(@grafana)",
"import/external-module-folders": ["node_modules", ".yarn"],

@ -178,6 +178,7 @@
"eslint-plugin-no-barrel-files": "^1.1.0",
"eslint-plugin-react": "7.34.2",
"eslint-plugin-react-hooks": "4.6.0",
"eslint-plugin-testing-library": "^6.2.2",
"eslint-scope": "^8.0.0",
"eslint-webpack-plugin": "4.2.0",
"expose-loader": "5.0.0",

@ -0,0 +1,9 @@
{
"plugins": ["testing-library"],
"overrides": [
{
"files": ["**/__tests__/**/*.[jt]s?(x)", "**/?(*.)+(spec|test).[jt]s?(x)"],
"extends": ["plugin:testing-library/react"],
},
],
}

@ -104,20 +104,20 @@ describe('CloneRuleEditor', function () {
await waitFor(() => {
expect(ui.inputs.name.get()).toHaveValue(`${grafanaRulerRule.grafana_alert.title} (copy)`);
expect(ui.inputs.folderContainer.get()).toHaveTextContent('folder-one');
expect(ui.inputs.group.get()).toHaveTextContent(grafanaRulerRule.grafana_alert.rule_group);
expect(
byRole('listitem', {
name: 'severity: critical',
}).get()
).toBeInTheDocument();
expect(
byRole('listitem', {
name: 'region: nasa',
}).get()
).toBeInTheDocument();
expect(ui.inputs.annotationValue(0).get()).toHaveTextContent(grafanaRulerRule.annotations[Annotation.summary]);
});
expect(ui.inputs.folderContainer.get()).toHaveTextContent('folder-one');
expect(ui.inputs.group.get()).toHaveTextContent(grafanaRulerRule.grafana_alert.rule_group);
expect(
byRole('listitem', {
name: 'severity: critical',
}).get()
).toBeInTheDocument();
expect(
byRole('listitem', {
name: 'region: nasa',
}).get()
).toBeInTheDocument();
expect(ui.inputs.annotationValue(0).get()).toHaveTextContent(grafanaRulerRule.annotations[Annotation.summary]);
});
});
@ -174,21 +174,21 @@ describe('CloneRuleEditor', function () {
await waitFor(() => {
expect(ui.inputs.name.get()).toHaveValue('First Ruler Rule (copy)');
expect(ui.inputs.expr.get()).toHaveValue('vector(1) > 0');
expect(ui.inputs.namespace.get()).toHaveTextContent('namespace-one');
expect(ui.inputs.group.get()).toHaveTextContent('group1');
expect(
byRole('listitem', {
name: 'severity: critical',
}).get()
).toBeInTheDocument();
expect(
byRole('listitem', {
name: 'region: nasa',
}).get()
).toBeInTheDocument();
expect(ui.inputs.annotationValue(0).get()).toHaveTextContent('This is a very important alert rule');
});
expect(ui.inputs.expr.get()).toHaveValue('vector(1) > 0');
expect(ui.inputs.namespace.get()).toHaveTextContent('namespace-one');
expect(ui.inputs.group.get()).toHaveTextContent('group1');
expect(
byRole('listitem', {
name: 'severity: critical',
}).get()
).toBeInTheDocument();
expect(
byRole('listitem', {
name: 'region: nasa',
}).get()
).toBeInTheDocument();
expect(ui.inputs.annotationValue(0).get()).toHaveTextContent('This is a very important alert rule');
});
});

@ -1,4 +1,4 @@
import { render, waitFor } from '@testing-library/react';
import { render, waitFor, screen } from '@testing-library/react';
import { TestProvider } from 'test/helpers/TestProvider';
import { DataSourceRef } from '@grafana/schema';
@ -73,12 +73,11 @@ describe('GrafanaRuleQueryViewer', () => {
getExpression('C', { type: '' }),
getExpression('D', { type: '' }),
];
const { getByTestId } = render(
<GrafanaRuleQueryViewer queries={[...queries, ...expressions]} condition="A" rule={rule} />,
{ wrapper: TestProvider }
);
render(<GrafanaRuleQueryViewer queries={[...queries, ...expressions]} condition="A" rule={rule} />, {
wrapper: TestProvider,
});
await waitFor(() => expect(getByTestId('queries-container')).toHaveStyle('flex-wrap: wrap'));
expect(getByTestId('expressions-container')).toHaveStyle('flex-wrap: wrap');
await waitFor(() => expect(screen.getByTestId('queries-container')).toHaveStyle('flex-wrap: wrap'));
expect(screen.getByTestId('expressions-container')).toHaveStyle('flex-wrap: wrap');
});
});

@ -183,7 +183,7 @@ describe('RuleEditor cloud: checking editable data sources', () => {
// render rule editor, select mimir/loki managed alerts
renderRuleEditor();
await waitForElementToBeRemoved(screen.getAllByTestId('Spinner'));
await waitForElementToBeRemoved(screen.queryAllByTestId('Spinner'));
await ui.inputs.name.find();

@ -113,13 +113,13 @@ describe('RuleEditor cloud', () => {
const user = userEvent.setup();
renderRuleEditor();
await waitForElementToBeRemoved(screen.getAllByTestId('Spinner'));
await waitForElementToBeRemoved(screen.queryAllByTestId('Spinner'));
const removeExpressionsButtons = screen.getAllByLabelText('Remove expression');
expect(removeExpressionsButtons).toHaveLength(2);
// Needs to wait for featrue discovery API call to finish - Check if ruler enabled
await waitFor(() => expect(screen.getByText('Data source-managed')).toBeInTheDocument());
expect(await screen.findByText('Data source-managed')).toBeInTheDocument();
const switchToCloudButton = screen.getByText('Data source-managed');
expect(switchToCloudButton).toBeInTheDocument();

@ -113,7 +113,7 @@ describe('RuleEditor grafana managed rules', () => {
] as DashboardSearchHit[]);
renderRuleEditor();
await waitForElementToBeRemoved(screen.getAllByTestId('Spinner'));
await waitForElementToBeRemoved(screen.queryAllByTestId('Spinner'));
await userEvent.type(await ui.inputs.name.find(), 'my great new rule');

@ -147,7 +147,7 @@ describe('RuleEditor recording rules', () => {
});
renderRuleEditor(undefined, true);
await waitForElementToBeRemoved(screen.getAllByTestId('Spinner'));
await waitForElementToBeRemoved(screen.queryAllByTestId('Spinner'));
await userEvent.type(await ui.inputs.name.find(), 'my great new recording rule');
const dataSourceSelect = ui.inputs.dataSource.get();

@ -2,7 +2,7 @@ import { SerializedError } from '@reduxjs/toolkit';
import userEvent from '@testing-library/user-event';
import { SetupServer } from 'msw/node';
import { TestProvider } from 'test/helpers/TestProvider';
import { prettyDOM, render, screen, waitFor, within } from 'test/test-utils';
import { render, screen, waitFor, within } from 'test/test-utils';
import { byRole, byTestId, byText } from 'testing-library-selector';
import { PluginExtensionTypes } from '@grafana/data';
@ -728,7 +728,6 @@ describe('RuleList', () => {
await userEvent.click(ui.editCloudGroupIcon.get(groups[0]));
await waitFor(() => expect(ui.editGroupModal.dialog.get()).toBeInTheDocument());
prettyDOM(ui.editGroupModal.dialog.get());
expect(ui.editGroupModal.namespaceInput.get()).toHaveDisplayValue('namespace1');
expect(ui.editGroupModal.ruleGroupInput.get()).toHaveDisplayValue('group1');

@ -49,10 +49,8 @@ describe('Alerting settings', () => {
it('should render the page with Built-in only enabled, others disabled', async () => {
render(<SettingsPage />);
await waitFor(() => {
expect(ui.builtInAlertmanagerSection.get()).toBeInTheDocument();
expect(ui.otherAlertmanagerSection.get()).toBeInTheDocument();
});
expect(await ui.builtInAlertmanagerSection.find()).toBeInTheDocument();
expect(ui.otherAlertmanagerSection.get()).toBeInTheDocument();
// check internal alertmanager configuration
expect(ui.builtInAlertmanagerCard.get()).toBeInTheDocument();

@ -90,11 +90,8 @@ describe('contact points', () => {
it('should show / hide loading states, have all actions enabled', async () => {
renderWithProvider(<ContactPointsPageContents />);
await waitFor(async () => {
expect(screen.getByText('Loading...')).toBeInTheDocument();
await waitForElementToBeRemoved(screen.getByText('Loading...'));
expect(screen.queryByTestId(selectors.components.Alert.alertV2('error'))).not.toBeInTheDocument();
});
await waitForElementToBeRemoved(screen.queryByText('Loading...'));
expect(screen.queryByTestId(selectors.components.Alert.alertV2('error'))).not.toBeInTheDocument();
expect(screen.getByText('grafana-default-email')).toBeInTheDocument();
expect(screen.getAllByTestId('contact-point')).toHaveLength(5);
@ -130,9 +127,7 @@ describe('contact points', () => {
renderWithProvider(<ContactPointsPageContents />);
// wait for loading to be done
await waitFor(async () => {
expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
});
await waitForElementToBeRemoved(screen.queryByText('Loading...'));
// should disable create contact point
expect(screen.getByRole('link', { name: 'add contact point' })).toHaveAttribute('aria-disabled', 'true');
@ -252,8 +247,8 @@ describe('contact points', () => {
await userEvent.type(searchInput, 'slack');
expect(searchInput).toHaveValue('slack');
expect(await screen.findByText('Slack with multiple channels')).toBeInTheDocument();
await waitFor(() => {
expect(screen.getByText('Slack with multiple channels')).toBeInTheDocument();
expect(screen.getAllByTestId('contact-point')).toHaveLength(1);
});
@ -286,11 +281,8 @@ describe('contact points', () => {
it('should show / hide loading states, have the right actions enabled', async () => {
renderWithProvider(<ContactPointsPageContents />, undefined, { alertmanagerSourceName: MIMIR_DATASOURCE_UID });
await waitFor(async () => {
expect(screen.getByText('Loading...')).toBeInTheDocument();
await waitForElementToBeRemoved(screen.getByText('Loading...'));
expect(screen.queryByTestId(selectors.components.Alert.alertV2('error'))).not.toBeInTheDocument();
});
await waitForElementToBeRemoved(screen.queryByText('Loading...'));
expect(screen.queryByTestId(selectors.components.Alert.alertV2('error'))).not.toBeInTheDocument();
expect(screen.getByText('mixed')).toBeInTheDocument();
expect(screen.getByText('some webhook')).toBeInTheDocument();
@ -344,11 +336,8 @@ describe('contact points', () => {
alertmanagerSourceName: VANILLA_ALERTMANAGER_DATASOURCE_UID,
});
await waitFor(async () => {
expect(screen.getByText('Loading...')).toBeInTheDocument();
await waitForElementToBeRemoved(screen.getByText('Loading...'));
expect(screen.queryByTestId(selectors.components.Alert.alertV2('error'))).not.toBeInTheDocument();
});
await waitForElementToBeRemoved(screen.queryByText('Loading...'));
expect(screen.queryByTestId(selectors.components.Alert.alertV2('error'))).not.toBeInTheDocument();
expect(screen.queryByRole('link', { name: 'add contact point' })).not.toBeInTheDocument();

@ -1,4 +1,4 @@
import { render, waitFor } from '@testing-library/react';
import { render, waitFor, screen } from '@testing-library/react';
import { Provider } from 'react-redux';
import { Router } from 'react-router-dom';
@ -36,15 +36,15 @@ describe('MuteTimingsTable', () => {
AccessControlAction.AlertingNotificationsRead,
AccessControlAction.AlertingNotificationsWrite,
]);
const { findByRole } = renderWithProvider();
expect(await findByRole('button', { name: /export all/i })).toBeInTheDocument();
renderWithProvider();
expect(await screen.findByRole('button', { name: /export all/i })).toBeInTheDocument();
});
it('It does not show export button when not allowed ', async () => {
// when not allowed
grantUserPermissions([]);
const { queryByRole } = renderWithProvider();
renderWithProvider();
await waitFor(() => {
expect(queryByRole('button', { name: /export all/i })).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: /export all/i })).not.toBeInTheDocument();
});
});
it('It does not show export button when not supported ', async () => {
@ -53,9 +53,9 @@ describe('MuteTimingsTable', () => {
AccessControlAction.AlertingNotificationsRead,
AccessControlAction.AlertingNotificationsWrite,
]);
const { queryByRole } = renderWithProvider('potato');
renderWithProvider('potato');
await waitFor(() => {
expect(queryByRole('button', { name: /export all/i })).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: /export all/i })).not.toBeInTheDocument();
});
});
});

@ -129,12 +129,12 @@ describe('TemplatePreview component', () => {
{ wrapper: getProviderWraper() }
);
const previews = ui.resultItems.getAll;
await waitFor(() => {
const previews = ui.resultItems.getAll();
expect(previews).toHaveLength(2);
expect(previews[0]).toHaveTextContent('This is the template result bla bla bla');
expect(previews[1]).toHaveTextContent('This is the template2 result bla bla bla');
expect(previews()).toHaveLength(2);
});
expect(previews()[0]).toHaveTextContent('This is the template result bla bla bla');
expect(previews()[1]).toHaveTextContent('This is the template2 result bla bla bla');
});
it('Should render preview response with some errors, if payload has correct format ', async () => {
@ -157,15 +157,14 @@ describe('TemplatePreview component', () => {
{ wrapper: getProviderWraper() }
);
const alerts = () => screen.getAllByTestId(Components.Alert.alertV2('error'));
await waitFor(() => {
const alerts = screen.getAllByTestId(Components.Alert.alertV2('error'));
const previewContent = screen.getByRole('listitem');
expect(alerts).toHaveLength(2);
expect(alerts[0]).toHaveTextContent(/Unexpected "{" in operand/i);
expect(alerts[1]).toHaveTextContent(/Unexpected "{" in operand/i);
expect(previewContent).toHaveTextContent('This is the template result bla bla bla');
expect(alerts()).toHaveLength(2);
});
expect(alerts()[0]).toHaveTextContent(/Unexpected "{" in operand/i);
expect(alerts()[1]).toHaveTextContent(/Unexpected "{" in operand/i);
const previewContent = screen.getByRole('listitem');
expect(previewContent).toHaveTextContent('This is the template result bla bla bla');
});
});

@ -51,9 +51,11 @@ describe('GrafanaReceiverForm', () => {
await clickSelectOption(byTestId('items.0.type').get(), 'Grafana OnCall');
// Clicking on a disable element shouldn't change the form value. email is the default value
// eslint-disable-next-line testing-library/no-node-access
expect(ui.integrationType.get().closest('form')).toHaveFormValues({ 'items.0.type': 'email' });
await clickSelectOption(byTestId('items.0.type').get(), 'Alertmanager');
// eslint-disable-next-line testing-library/no-node-access
expect(ui.integrationType.get().closest('form')).toHaveFormValues({ 'items.0.type': 'prometheus-alertmanager' });
});
@ -73,6 +75,7 @@ describe('GrafanaReceiverForm', () => {
await clickSelectOption(byTestId('items.0.type').get(), 'Grafana OnCall');
// eslint-disable-next-line testing-library/no-node-access
expect(ui.integrationType.get().closest('form')).toHaveFormValues({ 'items.0.type': 'oncall' });
expect(ui.onCallIntegrationType.get()).toBeInTheDocument();
@ -87,6 +90,7 @@ describe('GrafanaReceiverForm', () => {
await user.type(ui.newOnCallIntegrationName.get(), 'emea-oncall');
// eslint-disable-next-line testing-library/no-node-access
expect(ui.integrationType.get().closest('form')).toHaveFormValues({
'items.0.settings.integration_type': 'new_oncall_integration',
'items.0.settings.integration_name': 'emea-oncall',
@ -98,6 +102,7 @@ describe('GrafanaReceiverForm', () => {
await clickSelectOption(ui.existingOnCallIntegrationSelect(0).get(), 'apac-oncall');
// eslint-disable-next-line testing-library/no-node-access
expect(ui.integrationType.get().closest('form')).toHaveFormValues({
'items.0.settings.url': 'https://apac.oncall.example.com',
'items.0.settings.integration_name': undefined,

@ -1,6 +1,6 @@
import userEvent from '@testing-library/user-event';
import { FormProvider, useForm } from 'react-hook-form';
import { findByRole, findByText, findByTitle, getByTestId, queryByText, render } from 'test/test-utils';
import { screen, render, within } from 'test/test-utils';
import { byRole, byTestId } from 'testing-library-selector';
import 'core-js/stable/structured-clone';
@ -97,10 +97,10 @@ describe('AnnotationsField', function () {
await user.click(ui.setDashboardButton.get());
expect(ui.dashboardPicker.confirmButton.get()).toBeDisabled();
await user.click(await findByTitle(ui.dashboardPicker.dialog.get(), 'My dashboard'));
await user.click(await screen.findByTitle('My dashboard'));
expect(ui.dashboardPicker.confirmButton.get()).toBeDisabled();
await user.click(await findByText(ui.dashboardPicker.dialog.get(), 'First panel'));
await user.click(await screen.findByText('First panel'));
expect(ui.dashboardPicker.confirmButton.get()).toBeEnabled();
});
@ -125,9 +125,9 @@ describe('AnnotationsField', function () {
render(<FormWrapper formValues={{ annotations: [] }} />);
await user.click(ui.setDashboardButton.get());
await user.click(await findByTitle(ui.dashboardPicker.dialog.get(), 'My dashboard'));
await user.click(await screen.findByTitle('My dashboard'));
await user.click(await findByText(ui.dashboardPicker.dialog.get(), 'Second panel'));
await user.click(await screen.findByText('Second panel'));
await user.click(ui.dashboardPicker.confirmButton.get());
@ -163,10 +163,10 @@ describe('AnnotationsField', function () {
await user.click(ui.setDashboardButton.get());
expect(ui.dashboardPicker.confirmButton.get()).toBeDisabled();
await user.click(await findByTitle(ui.dashboardPicker.dialog.get(), 'My dashboard'));
await user.click(await screen.findByTitle('My dashboard'));
expect(await findByText(ui.dashboardPicker.dialog.get(), 'First panel')).toBeInTheDocument();
expect(await queryByText(ui.dashboardPicker.dialog.get(), 'Row panel')).not.toBeInTheDocument();
expect(await screen.findByText('First panel')).toBeInTheDocument();
expect(screen.queryByText('Row panel')).not.toBeInTheDocument();
});
it('should show panels within collapsed rows', async function () {
@ -198,11 +198,11 @@ describe('AnnotationsField', function () {
await user.click(ui.setDashboardButton.get());
expect(ui.dashboardPicker.confirmButton.get()).toBeDisabled();
await user.click(await findByTitle(ui.dashboardPicker.dialog.get(), 'My dashboard'));
await user.click(await screen.findByTitle('My dashboard'));
expect(await findByText(ui.dashboardPicker.dialog.get(), 'First panel')).toBeInTheDocument();
expect(await queryByText(ui.dashboardPicker.dialog.get(), 'Row panel')).not.toBeInTheDocument();
expect(await findByText(ui.dashboardPicker.dialog.get(), 'Panel within collapsed row')).toBeInTheDocument();
expect(await screen.findByText('First panel')).toBeInTheDocument();
expect(screen.queryByText('Row panel')).not.toBeInTheDocument();
expect(await screen.findByText('Panel within collapsed row')).toBeInTheDocument();
});
// this test _should_ work in theory but something is stopping the 'onClick' function on the dashboard item
@ -252,11 +252,11 @@ describe('AnnotationsField', function () {
expect(annotationValueElements[0]).toHaveTextContent('dash-test-uid');
expect(annotationValueElements[1]).toHaveTextContent('1');
const { confirmButton, dialog } = ui.dashboardPicker;
const { confirmButton } = ui.dashboardPicker;
await user.click(ui.setDashboardButton.get());
await user.click(await findByRole(dialog.get(), 'button', { name: /My other dashboard/ }));
await user.click(await findByRole(dialog.get(), 'button', { name: /Third panel/ }));
await user.click(await screen.findByRole('button', { name: /My other dashboard/ }));
await user.click(await screen.findByRole('button', { name: /Third panel/ }));
await user.click(confirmButton.get());
expect(ui.dashboardPicker.dialog.query()).not.toBeInTheDocument();
@ -296,14 +296,12 @@ describe('AnnotationsField', function () {
render(<FormWrapper formValues={{ annotations: [] }} />);
const { dialog } = ui.dashboardPicker;
await user.click(ui.setDashboardButton.get());
await user.click(await findByTitle(dialog.get(), 'My dashboard'));
await user.click(await screen.findByTitle('My dashboard'));
const warnedPanel = await findByRole(dialog.get(), 'button', { name: /First panel/ });
const warnedPanel = await screen.findByRole('button', { name: /First panel/ });
expect(getByTestId(warnedPanel, 'warning-icon')).toBeInTheDocument();
expect(within(warnedPanel).getByTestId('warning-icon')).toBeInTheDocument();
});
it('should render when panels do not contain certain fields', async () => {

@ -1,4 +1,4 @@
import { render, waitFor } from '@testing-library/react';
import { render } from '@testing-library/react';
import { noop } from 'lodash';
import { Props } from 'react-virtualized-auto-sizer';
import { byRole } from 'testing-library-selector';
@ -63,17 +63,15 @@ describe('DashboardPicker', () => {
wrapper: TestProvider,
});
await waitFor(() => {
expect(ui.dashboardButton(/Dashboard 1/).get()).toBeInTheDocument();
expect(ui.dashboardButton(/Dashboard 2/).get()).toBeInTheDocument();
expect(ui.dashboardButton(/Dashboard 3/).get()).toBeInTheDocument();
expect(await ui.dashboardButton(/Dashboard 1/).find()).toBeInTheDocument();
expect(ui.dashboardButton(/Dashboard 2/).get()).toBeInTheDocument();
expect(ui.dashboardButton(/Dashboard 3/).get()).toBeInTheDocument();
const panels = ui.dashboardButton(/<No title>/).getAll();
expect(panels).toHaveLength(3);
const panels = ui.dashboardButton(/<No title>/).getAll();
expect(panels).toHaveLength(3);
panels.forEach((panel) => {
expect(panel).not.toBeDisabled();
});
panels.forEach((panel) => {
expect(panel).not.toBeDisabled();
});
});
});

@ -1,6 +1,4 @@
import { screen } from '@testing-library/dom';
import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { render, screen, userEvent } from 'test/test-utils';
import { getEvaluationGroupOptions, EvaluationGroupQuickPick } from './EvaluationGroupQuickPick';

@ -1,6 +1,4 @@
import { screen } from '@testing-library/dom';
import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { render, screen, userEvent } from 'test/test-utils';
import { PendingPeriodQuickPick } from './PendingPeriodQuickPick';

@ -93,6 +93,7 @@ describe('Can create a new grafana managed alert unsing simplified routing', ()
const user = userEvent.setup();
renderSimplifiedRuleEditor();
await waitForElementToBeRemoved(screen.queryAllByTestId('Spinner'));
await user.type(await ui.inputs.name.find(), 'my great new rule');
@ -111,7 +112,7 @@ describe('Can create a new grafana managed alert unsing simplified routing', ()
it('simplified routing is not available when Grafana AM is not enabled', async () => {
setAlertmanagerChoices(AlertmanagerChoice.External, 1);
renderSimplifiedRuleEditor();
await waitForElementToBeRemoved(screen.getAllByTestId('Spinner'));
await waitForElementToBeRemoved(screen.queryAllByTestId('Spinner'));
expect(ui.inputs.simplifiedRouting.contactPointRouting.query()).not.toBeInTheDocument();
});
@ -121,6 +122,7 @@ describe('Can create a new grafana managed alert unsing simplified routing', ()
const contactPointName = 'lotsa-emails';
renderSimplifiedRuleEditor();
await waitForElementToBeRemoved(screen.queryAllByTestId('Spinner'));
await user.type(await ui.inputs.name.find(), 'my great new rule');

@ -147,14 +147,14 @@ describe('NotificationPreview', () => {
// we expect the alert manager label to be missing as there is only one alert manager configured to receive alerts
await waitFor(() => {
expect(ui.grafanaAlertManagerLabel.query()).not.toBeInTheDocument();
expect(ui.otherAlertManagerLabel.query()).not.toBeInTheDocument();
});
expect(ui.otherAlertManagerLabel.query()).not.toBeInTheDocument();
const matchingPoliciesElements = ui.route.queryAll;
await waitFor(() => {
const matchingPoliciesElements = ui.route.queryAll();
expect(matchingPoliciesElements).toHaveLength(1);
expect(matchingPoliciesElements[0]).toHaveTextContent(/tomato = red/);
expect(matchingPoliciesElements()).toHaveLength(1);
});
expect(matchingPoliciesElements()[0]).toHaveTextContent(/tomato = red/);
});
it('should render notification preview with alert manager sections, when having more than one alert manager configured to receive alerts', async () => {
// two alert managers configured to receive alerts
@ -174,8 +174,8 @@ describe('NotificationPreview', () => {
// we expect the alert manager label to be present as there is more than one alert manager configured to receive alerts
await waitFor(() => {
expect(ui.grafanaAlertManagerLabel.query()).toBeInTheDocument();
expect(ui.otherAlertManagerLabel.query()).toBeInTheDocument();
});
expect(ui.otherAlertManagerLabel.query()).toBeInTheDocument();
const matchingPoliciesElements = ui.route.queryAll();
expect(matchingPoliciesElements).toHaveLength(2);

@ -170,10 +170,8 @@ describe('RuleViewer', () => {
}
// actions
await waitFor(() => {
expect(ELEMENTS.actions.edit.get()).toBeInTheDocument();
expect(ELEMENTS.actions.more.button.get()).toBeInTheDocument();
});
expect(await ELEMENTS.actions.edit.find()).toBeInTheDocument();
expect(ELEMENTS.actions.more.button.get()).toBeInTheDocument();
// check the "more actions" button
await userEvent.click(ELEMENTS.actions.more.button.get());

@ -1,4 +1,4 @@
import { getByTestId, render } from '@testing-library/react';
import { screen, render } from '@testing-library/react';
import { byRole } from 'testing-library-selector';
import { LogRecordViewerByTimestamp } from './LogRecordViewer';
@ -22,8 +22,8 @@ describe('LogRecordViewerByTimestamp', () => {
const logElement = ui.log.get();
expect(logElement).toBeInTheDocument();
const entry1 = getByTestId(logElement, 1681739580000);
const entry2 = getByTestId(logElement, 1681739600000);
const entry1 = screen.getByTestId(1681739580000);
const entry2 = screen.getByTestId(1681739600000);
expect(entry1).toHaveTextContent('foo=bar');
expect(entry1).toHaveTextContent('severity=warning');

@ -39,10 +39,10 @@ describe('alertmanager abilities', () => {
})
);
const abilities = renderHook(() => useAllAlertmanagerAbilities(), {
const { result } = renderHook(() => useAllAlertmanagerAbilities(), {
wrapper: createAlertmanagerWrapper('does-not-exist'),
});
expect(abilities.result.current).toMatchSnapshot();
expect(result.current).toMatchSnapshot();
});
it('should report everything is supported for builtin alertmanager', () => {
@ -55,36 +55,36 @@ describe('alertmanager abilities', () => {
grantUserPermissions([AccessControlAction.AlertingNotificationsRead, AccessControlAction.AlertingInstanceRead]);
const abilities = renderHook(() => useAllAlertmanagerAbilities(), {
const { result } = renderHook(() => useAllAlertmanagerAbilities(), {
wrapper: createAlertmanagerWrapper(GRAFANA_RULES_SOURCE_NAME),
});
Object.values(abilities.result.current).forEach(([supported]) => {
Object.values(result.current).forEach(([supported]) => {
expect(supported).toBe(true);
});
// since we only granted "read" permissions, only those should be allowed
const viewAbility = renderHook(() => useAlertmanagerAbility(AlertmanagerAction.ViewSilence), {
const { result: viewResult } = renderHook(() => useAlertmanagerAbility(AlertmanagerAction.ViewSilence), {
wrapper: createAlertmanagerWrapper(GRAFANA_RULES_SOURCE_NAME),
});
const [viewSupported, viewAllowed] = viewAbility.result.current;
const [viewSupported, viewAllowed] = viewResult.current;
expect(viewSupported).toBe(true);
expect(viewAllowed).toBe(true);
// editing should not be allowed, but supported
const editAbility = renderHook(() => useAlertmanagerAbility(AlertmanagerAction.ViewSilence), {
const { result: editResult } = renderHook(() => useAlertmanagerAbility(AlertmanagerAction.ViewSilence), {
wrapper: createAlertmanagerWrapper(GRAFANA_RULES_SOURCE_NAME),
});
const [editSupported, editAllowed] = editAbility.result.current;
const [editSupported, editAllowed] = editResult.current;
expect(editSupported).toBe(true);
expect(editAllowed).toBe(true);
// record the snapshot to prevent future regressions
expect(abilities.result.current).toMatchSnapshot();
expect(result.current).toMatchSnapshot();
});
it('should report everything except exporting for Mimir alertmanager', () => {
@ -105,11 +105,11 @@ describe('alertmanager abilities', () => {
AccessControlAction.AlertingInstancesExternalWrite,
]);
const abilities = renderHook(() => useAllAlertmanagerAbilities(), {
const { result } = renderHook(() => useAllAlertmanagerAbilities(), {
wrapper: createAlertmanagerWrapper('mimir'),
});
expect(abilities.result.current).toMatchSnapshot();
expect(result.current).toMatchSnapshot();
});
it('should be able to return multiple abilities', () => {
@ -122,7 +122,7 @@ describe('alertmanager abilities', () => {
grantUserPermissions([AccessControlAction.AlertingNotificationsRead]);
const abilities = renderHook(
const { result } = renderHook(
() =>
useAlertmanagerAbilities([
AlertmanagerAction.ViewContactPoint,
@ -134,10 +134,10 @@ describe('alertmanager abilities', () => {
}
);
expect(abilities.result.current).toHaveLength(3);
expect(abilities.result.current[0]).toStrictEqual([true, true]);
expect(abilities.result.current[1]).toStrictEqual([true, false]);
expect(abilities.result.current[2]).toStrictEqual([true, true]);
expect(result.current).toHaveLength(3);
expect(result.current[0]).toStrictEqual([true, true]);
expect(result.current[1]).toStrictEqual([true, false]);
expect(result.current[2]).toStrictEqual([true, true]);
});
});
@ -163,17 +163,17 @@ describe('AlertRule abilities', () => {
it('should report that all actions are supported for a Grafana Managed alert rule', async () => {
const rule = getGrafanaRule();
const abilities = renderHook(() => useAllAlertRuleAbilities(rule), { wrapper: TestProvider });
const { result } = renderHook(() => useAllAlertRuleAbilities(rule), { wrapper: TestProvider });
await waitFor(() => {
const results = Object.values(abilities.result.current);
const results = Object.values(result.current);
for (const [supported, _allowed] of results) {
expect(supported).toBe(true);
}
});
expect(abilities.result.current).toMatchSnapshot();
expect(result.current).toMatchSnapshot();
});
it('grants correct silence permissions for folder with silence create permission', async () => {
@ -201,13 +201,13 @@ describe('AlertRule abilities', () => {
it('should report no permissions while we are loading data for cloud rule', async () => {
const rule = getCloudRule();
const abilities = renderHook(() => useAllAlertRuleAbilities(rule), { wrapper: TestProvider });
const { result } = renderHook(() => useAllAlertRuleAbilities(rule), { wrapper: TestProvider });
await waitFor(() => {
expect(abilities.result.current).not.toBeUndefined();
expect(result.current).not.toBeUndefined();
});
expect(abilities.result.current).toMatchSnapshot();
expect(result.current).toMatchSnapshot();
});
it('should not allow certain actions for provisioned rules', () => {});

@ -23,12 +23,10 @@ describe('useExternalDataSourceAlertmanagers', () => {
const { result } = renderHook(() => useExternalDataSourceAlertmanagers(), { wrapper: TestProvider });
await waitFor(() => {
// Assert
const { current } = result;
expect(current).toHaveLength(1);
expect(current[0].dataSourceSettings.uid).toBe('1');
expect(current[0].dataSourceSettings.url).toBe('http://grafana.com');
expect(result.current).toHaveLength(1);
});
expect(result.current[0].dataSourceSettings.uid).toBe('1');
expect(result.current[0].dataSourceSettings.url).toBe('http://grafana.com');
});
it('Should have uninterested state if data source does not want alerts', async () => {
@ -40,11 +38,9 @@ describe('useExternalDataSourceAlertmanagers', () => {
const { result } = renderHook(() => useExternalDataSourceAlertmanagers(), { wrapper: TestProvider });
await waitFor(() => {
// Assert
const { current } = result;
expect(current).toHaveLength(1);
expect(current[0].status).toBe('uninterested');
expect(result.current).toHaveLength(1);
});
expect(result.current[0].status).toBe('uninterested');
});
it('Should have active state if available in the activeAlertManagers', async () => {
@ -61,11 +57,9 @@ describe('useExternalDataSourceAlertmanagers', () => {
const { result } = renderHook(() => useExternalDataSourceAlertmanagers(), { wrapper: TestProvider });
await waitFor(() => {
// Assert
const { current } = result;
expect(current).toHaveLength(1);
expect(current[0].status).toBe('active');
expect(result.current).toHaveLength(1);
});
expect(result.current[0].status).toBe('active');
});
it('Should have dropped state if available in the droppedAlertManagers', async () => {
@ -83,11 +77,9 @@ describe('useExternalDataSourceAlertmanagers', () => {
await waitFor(() => {
// Assert
const { current } = result;
expect(current).toHaveLength(1);
expect(current[0].status).toBe('dropped');
expect(result.current).toHaveLength(1);
});
expect(result.current[0].status).toBe('dropped');
});
it('Should have pending state if not available neither in dropped nor in active alertManagers', async () => {
@ -105,11 +97,9 @@ describe('useExternalDataSourceAlertmanagers', () => {
await waitFor(() => {
// Assert
const { current } = result;
expect(current).toHaveLength(1);
expect(current[0].status).toBe('pending');
expect(result.current).toHaveLength(1);
});
expect(result.current[0].status).toBe('pending');
});
it('Should match Alertmanager url when datasource url does not have protocol specified', async () => {
@ -127,12 +117,10 @@ describe('useExternalDataSourceAlertmanagers', () => {
await waitFor(() => {
// Assert
const { current } = result;
expect(current).toHaveLength(1);
expect(current[0].status).toBe('active');
expect(current[0].dataSourceSettings.url).toBe('localhost:9093');
expect(result.current).toHaveLength(1);
});
expect(result.current[0].status).toBe('active');
expect(result.current[0].dataSourceSettings.url).toBe('localhost:9093');
});
it('Should have inconclusive state when there are many Alertmanagers of the same URL on both active and inactive', async () => {
@ -154,8 +142,8 @@ describe('useExternalDataSourceAlertmanagers', () => {
await waitFor(() => {
// Assert
expect(result.current).toHaveLength(1);
expect(result.current[0].status).toBe('inconclusive');
});
expect(result.current[0].status).toBe('inconclusive');
});
it('Should have not have inconclusive state when all Alertmanagers of the same URL are active', async () => {
@ -177,8 +165,8 @@ describe('useExternalDataSourceAlertmanagers', () => {
await waitFor(() => {
// Assert
expect(result.current).toHaveLength(1);
expect(result.current[0].status).toBe('active');
});
expect(result.current[0].status).toBe('active');
});
});

@ -285,7 +285,21 @@ __metadata:
languageName: node
linkType: hard
"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.18.9, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.24.0, @babel/helper-plugin-utils@npm:^7.24.5, @babel/helper-plugin-utils@npm:^7.24.7, @babel/helper-plugin-utils@npm:^7.24.8, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3":
"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.18.9, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.24.0, @babel/helper-plugin-utils@npm:^7.24.5, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3":
version: 7.24.5
resolution: "@babel/helper-plugin-utils@npm:7.24.5"
checksum: 10/6e11ca5da73e6bd366848236568c311ac10e433fc2034a6fe6243af28419b07c93b4386f87bbc940aa058b7c83f370ef58f3b0fd598106be040d21a3d1c14276
languageName: node
linkType: hard
"@babel/helper-plugin-utils@npm:^7.24.7":
version: 7.24.7
resolution: "@babel/helper-plugin-utils@npm:7.24.7"
checksum: 10/dad51622f0123fdba4e2d40a81a6b7d6ef4b1491b2f92fd9749447a36bde809106cf117358705057a2adc8fd73d5dc090222e0561b1213dae8601c8367f5aac8
languageName: node
linkType: hard
"@babel/helper-plugin-utils@npm:^7.24.8":
version: 7.24.8
resolution: "@babel/helper-plugin-utils@npm:7.24.8"
checksum: 10/adbc9fc1142800a35a5eb0793296924ee8057fe35c61657774208670468a9fbfbb216f2d0bc46c680c5fefa785e5ff917cc1674b10bd75cdf9a6aa3444780630
@ -347,6 +361,13 @@ __metadata:
languageName: node
linkType: hard
"@babel/helper-string-parser@npm:^7.24.7":
version: 7.24.7
resolution: "@babel/helper-string-parser@npm:7.24.7"
checksum: 10/603d8d962bbe89907aa99a8f19a006759ab7b2464615f20a6a22e3e2e8375af37ddd0e5175c9e622e1c4b2d83607ffb41055a59d0ce34404502af30fde573a5c
languageName: node
linkType: hard
"@babel/helper-string-parser@npm:^7.24.8":
version: 7.24.8
resolution: "@babel/helper-string-parser@npm:7.24.8"
@ -1605,7 +1626,18 @@ __metadata:
languageName: node
linkType: hard
"@babel/types@npm:^7.0.0, @babel/types@npm:^7.18.9, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.3, @babel/types@npm:^7.22.5, @babel/types@npm:^7.24.0, @babel/types@npm:^7.24.7, @babel/types@npm:^7.24.8, @babel/types@npm:^7.24.9, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3":
"@babel/types@npm:^7.0.0, @babel/types@npm:^7.18.9, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.3, @babel/types@npm:^7.22.5, @babel/types@npm:^7.24.0, @babel/types@npm:^7.24.7, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3":
version: 7.24.7
resolution: "@babel/types@npm:7.24.7"
dependencies:
"@babel/helper-string-parser": "npm:^7.24.7"
"@babel/helper-validator-identifier": "npm:^7.24.7"
to-fast-properties: "npm:^2.0.0"
checksum: 10/ad3c8c0d6fb4acb0bb74bb5b4bb849b181bf6185677ef9c59c18856c81e43628d0858253cf232f0eca806f02e08eff85a1d3e636a3e94daea737597796b0b430
languageName: node
linkType: hard
"@babel/types@npm:^7.24.8, @babel/types@npm:^7.24.9":
version: 7.24.9
resolution: "@babel/types@npm:7.24.9"
dependencies:
@ -2460,7 +2492,16 @@ __metadata:
languageName: node
linkType: hard
"@floating-ui/dom@npm:^1.0.0, @floating-ui/dom@npm:^1.0.1":
"@floating-ui/core@npm:^1.6.0":
version: 1.6.0
resolution: "@floating-ui/core@npm:1.6.0"
dependencies:
"@floating-ui/utils": "npm:^0.2.1"
checksum: 10/d6a47cacde193cd8ccb4c268b91ccc4ca254dffaec6242b07fd9bcde526044cc976d27933a7917f9a671de0a0e27f8d358f46400677dbd0c8199de293e9746e1
languageName: node
linkType: hard
"@floating-ui/dom@npm:^1.0.0":
version: 1.6.5
resolution: "@floating-ui/dom@npm:1.6.5"
dependencies:
@ -2470,6 +2511,16 @@ __metadata:
languageName: node
linkType: hard
"@floating-ui/dom@npm:^1.0.1":
version: 1.6.1
resolution: "@floating-ui/dom@npm:1.6.1"
dependencies:
"@floating-ui/core": "npm:^1.6.0"
"@floating-ui/utils": "npm:^0.2.1"
checksum: 10/c010feb55be37662eb4cc8d0a22e21359c25247bbdcd9557617fd305cf08c8f020435b17e4b4f410201ba9abe3a0dd96b5c42d56e85f7a5e11e7d30b85afc116
languageName: node
linkType: hard
"@floating-ui/react-dom@npm:^2.1.1":
version: 2.1.1
resolution: "@floating-ui/react-dom@npm:2.1.1"
@ -2503,6 +2554,13 @@ __metadata:
languageName: node
linkType: hard
"@floating-ui/utils@npm:^0.2.1":
version: 0.2.1
resolution: "@floating-ui/utils@npm:0.2.1"
checksum: 10/33c9ab346e7b05c5a1e6a95bc902aafcfc2c9d513a147e2491468843bd5607531b06d0b9aa56aa491cbf22a6c2495c18ccfc4c0344baec54a689a7bb8e4898d6
languageName: node
linkType: hard
"@formatjs/ecma402-abstract@npm:1.12.0":
version: 1.12.0
resolution: "@formatjs/ecma402-abstract@npm:1.12.0"
@ -4953,7 +5011,7 @@ __metadata:
languageName: node
linkType: hard
"@npmcli/package-json@npm:5.2.0, @npmcli/package-json@npm:^5.0.0, @npmcli/package-json@npm:^5.1.0":
"@npmcli/package-json@npm:5.2.0, @npmcli/package-json@npm:^5.1.0":
version: 5.2.0
resolution: "@npmcli/package-json@npm:5.2.0"
dependencies:
@ -4968,6 +5026,21 @@ __metadata:
languageName: node
linkType: hard
"@npmcli/package-json@npm:^5.0.0":
version: 5.1.0
resolution: "@npmcli/package-json@npm:5.1.0"
dependencies:
"@npmcli/git": "npm:^5.0.0"
glob: "npm:^10.2.2"
hosted-git-info: "npm:^7.0.0"
json-parse-even-better-errors: "npm:^3.0.0"
normalize-package-data: "npm:^6.0.0"
proc-log: "npm:^4.0.0"
semver: "npm:^7.5.3"
checksum: 10/0e5cb5eff32cf80234525160a702c91a38e4b98ab74e34e2632b43c4350dbad170bd835989cc7d6e18d24798e3242e45b60f3d5e26bd128fe1c4529931105f8e
languageName: node
linkType: hard
"@npmcli/promise-spawn@npm:^7.0.0":
version: 7.0.2
resolution: "@npmcli/promise-spawn@npm:7.0.2"
@ -5833,7 +5906,7 @@ __metadata:
languageName: node
linkType: hard
"@radix-ui/react-portal@npm:1.0.4, @radix-ui/react-portal@npm:^1.0.1":
"@radix-ui/react-portal@npm:1.0.4":
version: 1.0.4
resolution: "@radix-ui/react-portal@npm:1.0.4"
dependencies:
@ -5853,6 +5926,26 @@ __metadata:
languageName: node
linkType: hard
"@radix-ui/react-portal@npm:^1.0.1":
version: 1.0.3
resolution: "@radix-ui/react-portal@npm:1.0.3"
dependencies:
"@babel/runtime": "npm:^7.13.10"
"@radix-ui/react-primitive": "npm:1.0.3"
peerDependencies:
"@types/react": "*"
"@types/react-dom": "*"
react: ^16.8 || ^17.0 || ^18.0
react-dom: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
"@types/react":
optional: true
"@types/react-dom":
optional: true
checksum: 10/d352bcd6ad65eb43c9e0d72d0755c2aae85e03fb287770866262be3a2d5302b2885aee3cd99f2bbf62ecd14fcb1460703f1dcdc40351f77ad887b931c6f0012a
languageName: node
linkType: hard
"@radix-ui/react-presence@npm:1.0.1":
version: 1.0.1
resolution: "@radix-ui/react-presence@npm:1.0.1"
@ -8980,7 +9073,16 @@ __metadata:
languageName: node
linkType: hard
"@types/node@npm:*, @types/node@npm:20.14.13, @types/node@npm:>=13.7.0, @types/node@npm:^20.11.16":
"@types/node@npm:*, @types/node@npm:>=13.7.0, @types/node@npm:^20.11.16":
version: 20.14.2
resolution: "@types/node@npm:20.14.2"
dependencies:
undici-types: "npm:~5.26.4"
checksum: 10/c38e47b190fa0a8bdfde24b036dddcf9401551f2fb170a90ff33625c7d6f218907e81c74e0fa6e394804a32623c24c60c50e249badc951007830f0d02c48ee0f
languageName: node
linkType: hard
"@types/node@npm:20.14.13":
version: 20.14.13
resolution: "@types/node@npm:20.14.13"
dependencies:
@ -9278,7 +9380,7 @@ __metadata:
languageName: node
linkType: hard
"@types/semver@npm:7.5.8, @types/semver@npm:^7.3.4, @types/semver@npm:^7.5.0, @types/semver@npm:^7.5.8":
"@types/semver@npm:7.5.8, @types/semver@npm:^7.3.12, @types/semver@npm:^7.3.4, @types/semver@npm:^7.5.0, @types/semver@npm:^7.5.8":
version: 7.5.8
resolution: "@types/semver@npm:7.5.8"
checksum: 10/3496808818ddb36deabfe4974fd343a78101fa242c4690044ccdc3b95dcf8785b494f5d628f2f47f38a702f8db9c53c67f47d7818f2be1b79f2efb09692e1178
@ -9606,6 +9708,16 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/scope-manager@npm:5.62.0":
version: 5.62.0
resolution: "@typescript-eslint/scope-manager@npm:5.62.0"
dependencies:
"@typescript-eslint/types": "npm:5.62.0"
"@typescript-eslint/visitor-keys": "npm:5.62.0"
checksum: 10/e827770baa202223bc0387e2fd24f630690809e460435b7dc9af336c77322290a770d62bd5284260fa881c86074d6a9fd6c97b07382520b115f6786b8ed499da
languageName: node
linkType: hard
"@typescript-eslint/scope-manager@npm:6.18.1":
version: 6.18.1
resolution: "@typescript-eslint/scope-manager@npm:6.18.1"
@ -9670,6 +9782,13 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/types@npm:5.62.0":
version: 5.62.0
resolution: "@typescript-eslint/types@npm:5.62.0"
checksum: 10/24e8443177be84823242d6729d56af2c4b47bfc664dd411a1d730506abf2150d6c31bdefbbc6d97c8f91043e3a50e0c698239dcb145b79bb6b0c34469aaf6c45
languageName: node
linkType: hard
"@typescript-eslint/types@npm:6.18.1":
version: 6.18.1
resolution: "@typescript-eslint/types@npm:6.18.1"
@ -9691,6 +9810,24 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/typescript-estree@npm:5.62.0":
version: 5.62.0
resolution: "@typescript-eslint/typescript-estree@npm:5.62.0"
dependencies:
"@typescript-eslint/types": "npm:5.62.0"
"@typescript-eslint/visitor-keys": "npm:5.62.0"
debug: "npm:^4.3.4"
globby: "npm:^11.1.0"
is-glob: "npm:^4.0.3"
semver: "npm:^7.3.7"
tsutils: "npm:^3.21.0"
peerDependenciesMeta:
typescript:
optional: true
checksum: 10/06c975eb5f44b43bd19fadc2e1023c50cf87038fe4c0dd989d4331c67b3ff509b17fa60a3251896668ab4d7322bdc56162a9926971218d2e1a1874d2bef9a52e
languageName: node
linkType: hard
"@typescript-eslint/typescript-estree@npm:6.18.1":
version: 6.18.1
resolution: "@typescript-eslint/typescript-estree@npm:6.18.1"
@ -9782,6 +9919,24 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/utils@npm:^5.58.0":
version: 5.62.0
resolution: "@typescript-eslint/utils@npm:5.62.0"
dependencies:
"@eslint-community/eslint-utils": "npm:^4.2.0"
"@types/json-schema": "npm:^7.0.9"
"@types/semver": "npm:^7.3.12"
"@typescript-eslint/scope-manager": "npm:5.62.0"
"@typescript-eslint/types": "npm:5.62.0"
"@typescript-eslint/typescript-estree": "npm:5.62.0"
eslint-scope: "npm:^5.1.1"
semver: "npm:^7.3.7"
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
checksum: 10/15ef13e43998a082b15f85db979f8d3ceb1f9ce4467b8016c267b1738d5e7cdb12aa90faf4b4e6dd6486c236cf9d33c463200465cf25ff997dbc0f12358550a1
languageName: node
linkType: hard
"@typescript-eslint/utils@npm:^6.0.0 || ^7.0.0":
version: 7.8.0
resolution: "@typescript-eslint/utils@npm:7.8.0"
@ -9799,6 +9954,16 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/visitor-keys@npm:5.62.0":
version: 5.62.0
resolution: "@typescript-eslint/visitor-keys@npm:5.62.0"
dependencies:
"@typescript-eslint/types": "npm:5.62.0"
eslint-visitor-keys: "npm:^3.3.0"
checksum: 10/dc613ab7569df9bbe0b2ca677635eb91839dfb2ca2c6fa47870a5da4f160db0b436f7ec0764362e756d4164e9445d49d5eb1ff0b87f4c058946ae9d8c92eb388
languageName: node
linkType: hard
"@typescript-eslint/visitor-keys@npm:6.18.1":
version: 6.18.1
resolution: "@typescript-eslint/visitor-keys@npm:6.18.1"
@ -14011,7 +14176,7 @@ __metadata:
languageName: node
linkType: hard
"dedent@npm:1.5.3, dedent@npm:^1.0.0":
"dedent@npm:1.5.3":
version: 1.5.3
resolution: "dedent@npm:1.5.3"
peerDependencies:
@ -14030,6 +14195,18 @@ __metadata:
languageName: node
linkType: hard
"dedent@npm:^1.0.0":
version: 1.5.1
resolution: "dedent@npm:1.5.1"
peerDependencies:
babel-plugin-macros: ^3.1.0
peerDependenciesMeta:
babel-plugin-macros:
optional: true
checksum: 10/fc00a8bc3dfb7c413a778dc40ee8151b6c6ff35159d641f36ecd839c1df5c6e0ec5f4992e658c82624a1a62aaecaffc23b9c965ceb0bbf4d698bfc16469ac27d
languageName: node
linkType: hard
"deep-freeze@npm:0.0.1":
version: 0.0.1
resolution: "deep-freeze@npm:0.0.1"
@ -14771,7 +14948,7 @@ __metadata:
languageName: node
linkType: hard
"envinfo@npm:7.13.0, envinfo@npm:^7.7.3":
"envinfo@npm:7.13.0":
version: 7.13.0
resolution: "envinfo@npm:7.13.0"
bin:
@ -14780,6 +14957,15 @@ __metadata:
languageName: node
linkType: hard
"envinfo@npm:^7.7.3":
version: 7.8.1
resolution: "envinfo@npm:7.8.1"
bin:
envinfo: dist/cli.js
checksum: 10/e7a2d71c7dfe398a4ffda0e844e242d2183ef2627f98e74e4cd71edd2af691c8707a2b34aacef92538c27b3daf9a360d32202f33c0a9f27f767c4e1c6ba8b522
languageName: node
linkType: hard
"eol@npm:^0.9.1":
version: 0.9.1
resolution: "eol@npm:0.9.1"
@ -15386,7 +15572,18 @@ __metadata:
languageName: node
linkType: hard
"eslint-scope@npm:5.1.1":
"eslint-plugin-testing-library@npm:^6.2.2":
version: 6.2.2
resolution: "eslint-plugin-testing-library@npm:6.2.2"
dependencies:
"@typescript-eslint/utils": "npm:^5.58.0"
peerDependencies:
eslint: ^7.5.0 || ^8.0.0
checksum: 10/61947d0b81de1565c8627ec2d1e6636a8b6613cfe554a4671d011b3e88dfd77b498ce83b15bcf0a2df5570c44ad1d46d54058ed488f4e515d764196cbc6d65cf
languageName: node
linkType: hard
"eslint-scope@npm:5.1.1, eslint-scope@npm:^5.1.1":
version: 5.1.1
resolution: "eslint-scope@npm:5.1.1"
dependencies:
@ -17268,6 +17465,7 @@ __metadata:
eslint-plugin-no-barrel-files: "npm:^1.1.0"
eslint-plugin-react: "npm:7.34.2"
eslint-plugin-react-hooks: "npm:4.6.0"
eslint-plugin-testing-library: "npm:^6.2.2"
eslint-scope: "npm:^8.0.0"
eslint-webpack-plugin: "npm:4.2.0"
expose-loader: "npm:5.0.0"
@ -18147,7 +18345,16 @@ __metadata:
languageName: node
linkType: hard
"i18next@npm:^23.0.0, i18next@npm:^23.11.5, i18next@npm:^23.5.1":
"i18next@npm:^23.0.0, i18next@npm:^23.5.1":
version: 23.11.3
resolution: "i18next@npm:23.11.3"
dependencies:
"@babel/runtime": "npm:^7.23.2"
checksum: 10/9d562ade19d0beba16683ff94967a6dedc0a32ce335d203c5a160f075ac5a9a7a9adb164085a6b7b69328568bc932a65b92664834c2bf3e15d8f3bff90f15353
languageName: node
linkType: hard
"i18next@npm:^23.11.5":
version: 23.11.5
resolution: "i18next@npm:23.11.5"
dependencies:
@ -24316,7 +24523,7 @@ __metadata:
languageName: node
linkType: hard
"postcss-selector-parser@npm:^6.0.10, postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.15, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4, postcss-selector-parser@npm:^6.1.0":
"postcss-selector-parser@npm:^6.0.10":
version: 6.1.1
resolution: "postcss-selector-parser@npm:6.1.1"
dependencies:
@ -24326,6 +24533,16 @@ __metadata:
languageName: node
linkType: hard
"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.15, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4, postcss-selector-parser@npm:^6.1.0":
version: 6.1.0
resolution: "postcss-selector-parser@npm:6.1.0"
dependencies:
cssesc: "npm:^3.0.0"
util-deprecate: "npm:^1.0.2"
checksum: 10/2f9e5045b8bbe674fed3b79dbcd3daf21f5188cd7baf179beac513710ec3d75a8fc8184a262c3aec1c628ad3fd8bdb29c5d8530f1c9c5a61a18e1980bb000945
languageName: node
linkType: hard
"postcss-svgo@npm:^6.0.2":
version: 6.0.2
resolution: "postcss-svgo@npm:6.0.2"
@ -29279,13 +29496,24 @@ __metadata:
languageName: node
linkType: hard
"tslib@npm:^1.10.0, tslib@npm:^1.13.0":
"tslib@npm:^1.10.0, tslib@npm:^1.13.0, tslib@npm:^1.8.1":
version: 1.14.1
resolution: "tslib@npm:1.14.1"
checksum: 10/7dbf34e6f55c6492637adb81b555af5e3b4f9cc6b998fb440dac82d3b42bdc91560a35a5fb75e20e24a076c651438234da6743d139e4feabf0783f3cdfe1dddb
languageName: node
linkType: hard
"tsutils@npm:^3.21.0":
version: 3.21.0
resolution: "tsutils@npm:3.21.0"
dependencies:
tslib: "npm:^1.8.1"
peerDependencies:
typescript: ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
checksum: 10/ea036bec1dd024e309939ffd49fda7a351c0e87a1b8eb049570dd119d447250e2c56e0e6c00554e8205760e7417793fdebff752a46e573fbe07d4f375502a5b2
languageName: node
linkType: hard
"tuf-js@npm:^2.2.1":
version: 2.2.1
resolution: "tuf-js@npm:2.2.1"
@ -29399,13 +29627,20 @@ __metadata:
languageName: node
linkType: hard
"type-fest@npm:^4.18.2, type-fest@npm:^4.9.0":
"type-fest@npm:^4.18.2":
version: 4.18.3
resolution: "type-fest@npm:4.18.3"
checksum: 10/eb750920d0ef3639177f581edd6489d972c5c5827abb602a9c9662889aad148a7d558257e36c563f1beb81a2e417faec52ecec9799b28531d8335856f91e6dff
languageName: node
linkType: hard
"type-fest@npm:^4.9.0":
version: 4.10.2
resolution: "type-fest@npm:4.10.2"
checksum: 10/2b1ad1270d9fabeeb506ba831d513caeb05bfc852e5e012511d785ce9dc68d773fe0a42bddf857a362c7f3406244809c5b8a698b743bb7617d4a8c470672087f
languageName: node
linkType: hard
"type-is@npm:~1.6.18":
version: 1.6.18
resolution: "type-is@npm:1.6.18"

Loading…
Cancel
Save