add some eslint rules for testing-library use in tests

Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
Fredrik Adelöw
2022-11-16 09:32:58 +01:00
parent fd7ec12ec2
commit cb716004ef
31 changed files with 236 additions and 134 deletions
+9
View File
@@ -0,0 +1,9 @@
---
'@backstage/plugin-catalog-graph': patch
'@backstage/plugin-pagerduty': patch
'@backstage/plugin-scaffolder-backend': patch
'@backstage/plugin-splunk-on-call': patch
'@backstage/plugin-techdocs-react': patch
---
Internal refactor to improve tests
+6 -1
View File
@@ -18,7 +18,7 @@ var path = require('path');
module.exports = {
root: true,
plugins: ['notice'],
plugins: ['notice', 'testing-library'],
rules: {
'notice/notice': [
'error',
@@ -45,5 +45,10 @@ module.exports = {
"CallExpression[arguments.length=0] > MemberExpression[property.name='toUpperCase']",
},
],
'testing-library/await-async-query': 'error',
'testing-library/await-async-utils': 'error',
'testing-library/no-await-sync-query': 'error',
'testing-library/prefer-wait-for': 'error',
'testing-library/no-dom-import': 'error',
},
};
+1
View File
@@ -71,6 +71,7 @@
"e2e-test": "workspace:*",
"eslint": "^8.6.0",
"eslint-plugin-notice": "^0.9.10",
"eslint-plugin-testing-library": "^5.9.1",
"fs-extra": "10.1.0",
"husky": "^8.0.0",
"lint-staged": "^13.0.0",
+4
View File
@@ -25,14 +25,17 @@ describe('App', () => {
it('should display support info when clicking the button', () => {
cy.visit('/');
// eslint-disable-next-line testing-library/await-async-query
cy.findByTestId('support-button').click({ force: true });
cy.contains('#backstage');
});
it('should display error message when triggering it', () => {
cy.visit('/');
// eslint-disable-next-line testing-library/await-async-query
cy.findByTestId('error-button').click({ force: true });
cy.contains('Error: Oh no!');
// eslint-disable-next-line testing-library/await-async-query
cy.findByTestId('error-button-close').click({ force: true });
});
@@ -55,6 +58,7 @@ describe('App', () => {
cy.contains('Token')
.get('input[name=github-auth-tf]')
.type('password', { force: true });
// eslint-disable-next-line testing-library/await-async-query
cy.findByTestId('github-auth-button').click({ force: true });
cy.contains(`Welcome, ${name}!`);
cy.contains('Logout').click({ force: true });
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { FeatureFlagged } from './FeatureFlagged';
import { render } from '@testing-library/react';
@@ -44,7 +45,7 @@ describe('FeatureFlagged', () => {
</Wrapper>,
);
expect(await queryByText('BACKSTAGE!')).toBeInTheDocument();
expect(queryByText('BACKSTAGE!')).toBeInTheDocument();
});
it('should not render contents when the feature flag is disabled', async () => {
jest
@@ -61,7 +62,7 @@ describe('FeatureFlagged', () => {
</Wrapper>,
);
expect(await queryByText('BACKSTAGE!')).not.toBeInTheDocument();
expect(queryByText('BACKSTAGE!')).not.toBeInTheDocument();
});
});
describe('without', () => {
@@ -80,7 +81,7 @@ describe('FeatureFlagged', () => {
</Wrapper>,
);
expect(await queryByText('BACKSTAGE!')).not.toBeInTheDocument();
expect(queryByText('BACKSTAGE!')).not.toBeInTheDocument();
});
it('should render contents when the feature flag is disabled', async () => {
jest
@@ -97,7 +98,7 @@ describe('FeatureFlagged', () => {
</Wrapper>,
);
expect(await queryByText('BACKSTAGE!')).toBeInTheDocument();
expect(queryByText('BACKSTAGE!')).toBeInTheDocument();
});
});
});
@@ -70,8 +70,8 @@ describe('<FeatureCalloutCircular />', () => {
description="description"
/>,
);
const dot = await getByTestId('dot');
const text = await getByTestId('text');
const dot = getByTestId('dot');
const text = getByTestId('text');
expect(dot).toBeInTheDocument();
expect(text).toBeInTheDocument();
@@ -96,8 +96,8 @@ describe('<FeatureCalloutCircular />', () => {
description="description"
/>,
);
const dot = await getByTestId('dot');
const text = await getByTestId('text');
const dot = getByTestId('dot');
const text = getByTestId('text');
act(() => {
Element.prototype.getBoundingClientRect = jest.fn(
@@ -128,8 +128,8 @@ describe('<FeatureCalloutCircular />', () => {
description="description"
/>,
);
const dot = await getByTestId('dot');
const text = await getByTestId('text');
const dot = getByTestId('dot');
const text = getByTestId('text');
act(() => {
Element.prototype.getBoundingClientRect = jest.fn(
@@ -41,7 +41,7 @@ describe('<Select />', () => {
const { getByText, getByTestId } = render(<Select {...minProps} />);
expect(getByText('Default')).toBeInTheDocument();
const input = await getByTestId('select');
const input = getByTestId('select');
expect(input.textContent).toBe('All results');
// Simulate click on input
@@ -18,7 +18,6 @@ import React from 'react';
import { fireEvent, screen } from '@testing-library/react';
import { renderInTestApp } from '@backstage/test-utils';
import Typography from '@material-ui/core/Typography';
import { WarningPanel, WarningProps } from './WarningPanel';
const propsTitle: WarningProps = { title: 'Mock title' };
@@ -41,7 +40,7 @@ describe('<WarningPanel />', () => {
it('renders title', async () => {
await renderInTestApp(<WarningPanel {...propsTitleMessage} />);
const expandIcon = await screen.getByText('Warning: Mock title');
const expandIcon = screen.getByText('Warning: Mock title');
fireEvent.click(expandIcon);
expect(screen.getByText('Warning: Mock title')).toBeInTheDocument();
expect(screen.getByText('Some more info')).toBeInTheDocument();
@@ -46,7 +46,7 @@ describe('BitriseArtifactsComponent', () => {
const rendered = renderComponent();
const btn = await rendered.findByTestId('btn');
expect(await rendered.queryByText('VISIBLE')).not.toBeInTheDocument();
expect(rendered.queryByText('VISIBLE')).not.toBeInTheDocument();
btn.click();
@@ -13,64 +13,65 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { render, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { render, screen } from '@testing-library/react';
import user from '@testing-library/user-event';
import React from 'react';
import { MaxDepthFilter } from './MaxDepthFilter';
describe('<MaxDepthFilter/>', () => {
test('should display current value', () => {
const { getByLabelText } = render(
<MaxDepthFilter value={5} onChange={() => {}} />,
);
render(<MaxDepthFilter value={5} onChange={() => {}} />);
expect(getByLabelText('maxp')).toBeInTheDocument();
expect(getByLabelText('maxp')).toHaveValue(5);
expect(screen.getByLabelText('maxp')).toBeInTheDocument();
expect(screen.getByLabelText('maxp')).toHaveValue(5);
});
test('should display infinite if non finite', () => {
const { getByPlaceholderText, getByLabelText } = render(
render(
<MaxDepthFilter value={Number.POSITIVE_INFINITY} onChange={() => {}} />,
);
expect(getByPlaceholderText(/Infinite/)).toBeInTheDocument();
expect(getByLabelText('maxp')).toHaveValue(null);
expect(screen.getByPlaceholderText(/Infinite/)).toBeInTheDocument();
expect(screen.getByLabelText('maxp')).toHaveValue(null);
});
test('should clear max depth', async () => {
const onChange = jest.fn();
const { getByLabelText } = render(
<MaxDepthFilter value={10} onChange={onChange} />,
);
render(<MaxDepthFilter value={10} onChange={onChange} />);
await userEvent.click(getByLabelText('clear max depth'));
expect(onChange).not.toHaveBeenCalled();
await user.click(screen.getByLabelText('clear max depth'));
expect(onChange).toHaveBeenCalledWith(Number.POSITIVE_INFINITY);
});
test('should set max depth to undefined if below one', async () => {
const onChange = jest.fn();
const { getByLabelText } = render(
<MaxDepthFilter value={1} onChange={onChange} />,
);
render(<MaxDepthFilter value={1} onChange={onChange} />);
await userEvent.clear(getByLabelText('maxp'));
await userEvent.type(getByLabelText('maxp'), '0');
await user.clear(screen.getByLabelText('maxp'));
await user.type(screen.getByLabelText('maxp'), '0');
expect(onChange).toHaveBeenCalledWith(Number.POSITIVE_INFINITY);
});
test('should select direction', async () => {
const onChange = jest.fn();
const { getByLabelText } = render(
<MaxDepthFilter value={5} onChange={onChange} />,
let value = 5;
render(
<MaxDepthFilter
value={value}
onChange={v => {
value = v;
}}
/>,
);
expect(getByLabelText('maxp')).toHaveValue(5);
expect(screen.getByLabelText('maxp')).toHaveValue(5);
expect(value).toBe(5);
await userEvent.clear(getByLabelText('maxp'));
await userEvent.type(getByLabelText('maxp'), '10');
waitFor(() => {
expect(onChange).toHaveBeenCalledWith(10);
});
await user.clear(screen.getByLabelText('maxp'));
expect(value).toBe(Number.POSITIVE_INFINITY);
await user.type(screen.getByLabelText('maxp'), '10');
expect(value).toBe(10);
});
});
@@ -23,7 +23,7 @@ import {
Typography,
} from '@material-ui/core';
import ClearIcon from '@material-ui/icons/Clear';
import React, { useCallback } from 'react';
import React, { useCallback, useEffect, useRef, useState } from 'react';
export type Props = {
value: number;
@@ -42,18 +42,37 @@ const useStyles = makeStyles(
export const MaxDepthFilter = ({ value, onChange }: Props) => {
const classes = useStyles();
const onChangeRef = useRef(onChange);
const [currentValue, setCurrentValue] = useState(value);
// Keep a fresh reference to the latest callback
useEffect(() => {
onChangeRef.current = onChange;
}, [onChange]);
// If the value changes externally, update ourselves
useEffect(() => {
setCurrentValue(value);
}, [value]);
// When the entered text changes, update ourselves and communicate externally
const handleChange = useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => {
const v = Number(event.target.value);
onChange(v <= 0 ? Number.POSITIVE_INFINITY : v);
const newValueNumeric = Number(event.target.value);
const newValue =
Number.isFinite(newValueNumeric) && newValueNumeric > 0
? newValueNumeric
: Number.POSITIVE_INFINITY;
setCurrentValue(newValue);
onChangeRef.current(newValue);
},
[onChange],
[],
);
const reset = useCallback(() => {
onChange(Number.POSITIVE_INFINITY);
}, [onChange]);
setCurrentValue(Number.POSITIVE_INFINITY);
onChangeRef.current(Number.POSITIVE_INFINITY);
}, [onChangeRef]);
return (
<Box pb={1} pt={1}>
@@ -62,7 +81,7 @@ export const MaxDepthFilter = ({ value, onChange }: Props) => {
<OutlinedInput
type="number"
placeholder="∞ Infinite"
value={isFinite(value) ? value : ''}
value={Number.isFinite(currentValue) ? String(currentValue) : ''}
onChange={handleChange}
endAdornment={
<InputAdornment position="end">
@@ -75,7 +75,7 @@ describe('ComponentContextMenu', () => {
expect(button).toBeInTheDocument();
fireEvent.click(button);
const unregister = await screen.getByText('Unregister entity');
const unregister = screen.getByText('Unregister entity');
expect(unregister).toBeInTheDocument();
const unregisterSpanItem = getByText(/Unregister entity/);
@@ -69,7 +69,7 @@ describe('ComponentContextMenu', () => {
/>,
);
const unregister = await screen.getByText('Unregister entity');
const unregister = screen.getByText('Unregister entity');
expect(unregister).toBeInTheDocument();
const unregisterSpanItem = getByText(/Unregister entity/);
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { SyntheticsLocation } from './SyntheticsLocation';
import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils';
@@ -60,6 +61,6 @@ describe('SyntheticsLocation', () => {
</ApiProvider>,
);
expect(await rendered.findByText(/__location__/)).toBeInTheDocument();
expect(await rendered.queryByText(/failed/)).not.toBeInTheDocument();
expect(rendered.queryByText(/failed/)).not.toBeInTheDocument();
});
});
@@ -40,7 +40,7 @@ describe('Select', () => {
expect(rendered.getAllByText(testLabel)).toHaveLength(2);
});
describe('when the user hasn`t clicked on it', () => {
describe("when the user hasn't clicked on it", () => {
it('should only render the current select item', async () => {
const rendered = await renderInTestApp(
<SelectComponent
@@ -122,7 +122,7 @@ describe('<AuditListTableForEntity />', () => {
it('renders nothing', async () => {
const { queryByTestId } = subject();
expect(await queryByTestId('AuditListTable')).toBeNull();
expect(queryByTestId('AuditListTable')).toBeNull();
});
});
@@ -137,7 +137,7 @@ describe('<AuditListTableForEntity />', () => {
it('renders nothing', async () => {
const { queryByTestId } = subject();
expect(await queryByTestId('AuditListTable')).toBeNull();
expect(queryByTestId('AuditListTable')).toBeNull();
});
});
});
@@ -151,10 +151,10 @@ describe('<LastLighthouseAuditCard />', () => {
it('renders nothing', async () => {
const { queryByTestId } = subject();
expect(await queryByTestId('AuditListTable')).toBeNull();
expect(queryByTestId('AuditListTable')).toBeNull();
});
});
//
describe('where there is no data', () => {
beforeEach(() => {
(useWebsiteForEntity as jest.Mock).mockReturnValue({
@@ -166,7 +166,7 @@ describe('<LastLighthouseAuditCard />', () => {
it('renders nothing', async () => {
const { queryByTestId } = subject();
expect(await queryByTestId('AuditListTable')).toBeNull();
expect(queryByTestId('AuditListTable')).toBeNull();
});
});
});
@@ -15,7 +15,8 @@
*/
import React from 'react';
import { fireEvent, render, waitFor } from '@testing-library/react';
import { render, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { ApiProvider } from '@backstage/core-app-api';
import { catalogApiRef } from '@backstage/plugin-catalog-react';
import { CatalogApi } from '@backstage/catalog-client';
@@ -74,13 +75,13 @@ describe('<GroupListPicker />', () => {
</ApiProvider>,
);
fireEvent.click(getByTestId('group-list-picker-button'));
await userEvent.click(getByTestId('group-list-picker-button'));
const input = getByTestId('group-list-picker-input').querySelector('input');
fireEvent.change(input as HTMLElement, { target: { value: 'GR' } });
await userEvent.type(input as HTMLElement, 'GR');
await waitFor(async () => {
expect(getByText('Group A')).toBeInTheDocument();
fireEvent.click(getByText('Group A'));
await userEvent.click(getByText('Group A'));
expect(getByText('Group A')).toBeInTheDocument();
});
});
+6 -6
View File
@@ -73,7 +73,7 @@ export class PagerDutyClient implements PagerDutyApi {
url = `${await this.config.discoveryApi.getBaseUrl(
'proxy',
)}/pagerduty/services?${commonGetServiceParams}&query=${integrationKey}`;
const { services } = await this.getByUrl<PagerDutyServicesResponse>(url);
const { services } = await this.findByUrl<PagerDutyServicesResponse>(url);
const service = services[0];
if (!service) throw new NotFoundError();
@@ -84,7 +84,7 @@ export class PagerDutyClient implements PagerDutyApi {
'proxy',
)}/pagerduty/services/${serviceId}?${commonGetServiceParams}`;
response = await this.getByUrl<PagerDutyServiceResponse>(url);
response = await this.findByUrl<PagerDutyServiceResponse>(url);
} else {
throw new NotFoundError();
}
@@ -100,7 +100,7 @@ export class PagerDutyClient implements PagerDutyApi {
'proxy',
)}/pagerduty/incidents?${params}`;
return await this.getByUrl<PagerDutyIncidentsResponse>(url);
return await this.findByUrl<PagerDutyIncidentsResponse>(url);
}
async getChangeEventsByServiceId(
@@ -111,7 +111,7 @@ export class PagerDutyClient implements PagerDutyApi {
'proxy',
)}/pagerduty/services/${serviceId}/change_events?${params}`;
return await this.getByUrl<PagerDutyChangeEventsResponse>(url);
return await this.findByUrl<PagerDutyChangeEventsResponse>(url);
}
async getOnCallByPolicyId(
@@ -122,7 +122,7 @@ export class PagerDutyClient implements PagerDutyApi {
'proxy',
)}/pagerduty/oncalls?${params}`;
return await this.getByUrl<PagerDutyOnCallsResponse>(url);
return await this.findByUrl<PagerDutyOnCallsResponse>(url);
}
triggerAlarm(request: PagerDutyTriggerAlarmRequest): Promise<Response> {
@@ -158,7 +158,7 @@ export class PagerDutyClient implements PagerDutyApi {
return this.request(`${url}/enqueue`, options);
}
private async getByUrl<T>(url: string): Promise<T> {
private async findByUrl<T>(url: string): Promise<T> {
const options = {
method: 'GET',
headers: {
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Config } from '@backstage/config';
import { assertError, InputError } from '@backstage/errors';
import {
@@ -124,6 +125,7 @@ export async function createGithubRepoWithCollaboratorsAndTopics(
topics: string[] | undefined,
logger: Logger,
) {
// eslint-disable-next-line testing-library/no-await-sync-query
const user = await client.rest.users.getByUsername({
username: owner,
});
@@ -236,7 +236,7 @@ describe('<ListTasksPage />', () => {
);
await act(async () => {
const allButton = await getByText('All');
const allButton = getByText('All');
fireEvent.click(allButton);
});
@@ -15,7 +15,6 @@
*/
import { renderInTestApp } from '@backstage/test-utils';
import React from 'react';
import { OwnerListPicker } from './OwnerListPicker';
import { fireEvent } from '@testing-library/react';
@@ -29,8 +28,8 @@ describe('<OwnerListPicker />', () => {
const { getByText } = await renderInTestApp(<OwnerListPicker {...props} />);
expect(await getByText('Owned')).toBeDefined();
expect(await getByText('All')).toBeDefined();
expect(getByText('Owned')).toBeDefined();
expect(getByText('All')).toBeDefined();
});
it('should call the function on select other item', async () => {
@@ -41,7 +40,7 @@ describe('<OwnerListPicker />', () => {
const { getByText } = await renderInTestApp(<OwnerListPicker {...props} />);
fireEvent.click(await getByText('All'));
fireEvent.click(getByText('All'));
expect(props.onSelectOwner).toHaveBeenCalledWith('all');
});
});
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
MockAnalyticsApi,
renderInTestApp,
@@ -340,9 +341,9 @@ describe('TemplatePage', () => {
},
);
expect(await queryByText('Name')).not.toBeInTheDocument();
expect(await queryByText('Description')).toBeInTheDocument();
expect(await queryByText('Owner')).toBeInTheDocument();
expect(await queryByText('Send data')).toBeInTheDocument();
expect(queryByText('Name')).not.toBeInTheDocument();
expect(queryByText('Description')).toBeInTheDocument();
expect(queryByText('Owner')).toBeInTheDocument();
expect(queryByText('Send data')).toBeInTheDocument();
});
});
@@ -34,7 +34,7 @@ describe('RegisterExistingButton', () => {
<RegisterExistingButton title="Pick me" />,
);
expect(await queryByText('Pick me')).not.toBeInTheDocument();
expect(queryByText('Pick me')).not.toBeInTheDocument();
});
it('should not render if permissions are not allowed', async () => {
@@ -43,7 +43,7 @@ describe('RegisterExistingButton', () => {
<RegisterExistingButton title="Pick me" to="blah" />,
);
expect(await queryByText('Pick me')).not.toBeInTheDocument();
expect(queryByText('Pick me')).not.toBeInTheDocument();
});
it('should render the button with the text', async () => {
@@ -52,6 +52,6 @@ describe('RegisterExistingButton', () => {
<RegisterExistingButton title="Pick me" to="blah" />,
);
expect(await queryByText('Pick me')).toBeInTheDocument();
expect(queryByText('Pick me')).toBeInTheDocument();
});
});
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { ReviewState } from './ReviewState';
import { render } from '@testing-library/react';
@@ -97,9 +98,7 @@ describe('ReviewState', () => {
<ReviewState formState={formState} schemas={schemas} />,
);
expect(
await queryByRole('row', { name: 'Name ******' }),
).not.toBeInTheDocument();
expect(queryByRole('row', { name: 'Name ******' })).not.toBeInTheDocument();
});
it('should allow for masking an option with a set text', () => {
+7 -7
View File
@@ -64,7 +64,7 @@ export class SplunkOnCallClient implements SplunkOnCallApi {
'proxy',
)}/splunk-on-call/v1/incidents`;
const { incidents } = await this.getByUrl<IncidentsResponse>(url);
const { incidents } = await this.findByUrl<IncidentsResponse>(url);
return incidents;
}
@@ -73,7 +73,7 @@ export class SplunkOnCallClient implements SplunkOnCallApi {
const url = `${await this.config.discoveryApi.getBaseUrl(
'proxy',
)}/splunk-on-call/v1/oncall/current`;
const { teamsOnCall } = await this.getByUrl<OnCallsResponse>(url);
const { teamsOnCall } = await this.findByUrl<OnCallsResponse>(url);
return teamsOnCall;
}
@@ -82,7 +82,7 @@ export class SplunkOnCallClient implements SplunkOnCallApi {
const url = `${await this.config.discoveryApi.getBaseUrl(
'proxy',
)}/splunk-on-call/v1/team`;
const teams = await this.getByUrl<Team[]>(url);
const teams = await this.findByUrl<Team[]>(url);
return teams;
}
@@ -91,7 +91,7 @@ export class SplunkOnCallClient implements SplunkOnCallApi {
const url = `${await this.config.discoveryApi.getBaseUrl(
'proxy',
)}/splunk-on-call/v1/org/routing-keys`;
const { routingKeys } = await this.getByUrl<ListRoutingKeyResponse>(url);
const { routingKeys } = await this.findByUrl<ListRoutingKeyResponse>(url);
return routingKeys;
}
@@ -100,7 +100,7 @@ export class SplunkOnCallClient implements SplunkOnCallApi {
const url = `${await this.config.discoveryApi.getBaseUrl(
'proxy',
)}/splunk-on-call/v2/user`;
const { users } = await this.getByUrl<ListUserResponse>(url);
const { users } = await this.findByUrl<ListUserResponse>(url);
return users;
}
@@ -109,7 +109,7 @@ export class SplunkOnCallClient implements SplunkOnCallApi {
const url = `${await this.config.discoveryApi.getBaseUrl(
'proxy',
)}/splunk-on-call/v1/policies`;
const { policies } = await this.getByUrl<EscalationPolicyResponse>(url);
const { policies } = await this.findByUrl<EscalationPolicyResponse>(url);
return policies;
}
@@ -146,7 +146,7 @@ export class SplunkOnCallClient implements SplunkOnCallApi {
return this.request(url, options);
}
private async getByUrl<T>(url: string): Promise<T> {
private async findByUrl<T>(url: string): Promise<T> {
const options = {
method: 'GET',
headers: {
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Entity } from '@backstage/catalog-model';
import { ApiProvider, ConfigReader } from '@backstage/core-app-api';
import {
@@ -187,7 +188,7 @@ describe('SplunkOnCallCard', () => {
{ timeout: 2000 },
);
const createIncidentButton = await getByText('Create Incident');
const createIncidentButton = getByText('Create Incident');
await act(async () => {
fireEvent.click(createIncidentButton);
});
+1 -1
View File
@@ -173,7 +173,7 @@ export const useShadowRootElements: <
) => TReturnedElement[];
// @public
export const useShadowRootSelection: (wait?: number) => Selection | null;
export const useShadowRootSelection: (waitMillis?: number) => Selection | null;
// @public
export const useTechDocsAddons: () => {
+4 -4
View File
@@ -57,10 +57,10 @@ const isValidSelection = (newSelection: Selection) => {
};
/**
* Hook for retreiving a selection within the ShadowRoot.
* Hook for retrieving a selection within the ShadowRoot.
* @public
*/
export const useShadowRootSelection = (wait: number = 0) => {
export const useShadowRootSelection = (waitMillis: number = 0) => {
const shadowRoot = useShadowRoot();
const [selection, setSelection] = useState<Selection | null>(null);
const handleSelectionChange = useMemo(
@@ -78,8 +78,8 @@ export const useShadowRootSelection = (wait: number = 0) => {
} else {
setSelection(null);
}
}, wait),
[shadowRoot, setSelection, wait],
}, waitMillis),
[shadowRoot, setSelection, waitMillis],
);
useEffect(() => {
@@ -103,10 +103,10 @@ describe('Entity List Docs Grid', () => {
},
);
expect(await screen.queryByText('All Documentation')).toBeInTheDocument();
expect(await screen.queryByText('Documentation #1')).toBeInTheDocument();
expect(await screen.queryByText('Documentation #2')).toBeInTheDocument();
expect(await screen.queryByTestId('doc-not-found')).not.toBeInTheDocument();
expect(screen.queryByText('All Documentation')).toBeInTheDocument();
expect(screen.queryByText('Documentation #1')).toBeInTheDocument();
expect(screen.queryByText('Documentation #2')).toBeInTheDocument();
expect(screen.queryByTestId('doc-not-found')).not.toBeInTheDocument();
});
it('should render only filtered entities with filtering', async () => {
@@ -131,14 +131,10 @@ describe('Entity List Docs Grid', () => {
},
);
expect(
await screen.queryByText('Curated Documentation'),
).toBeInTheDocument();
expect(await screen.queryByText('Documentation #1')).toBeInTheDocument();
expect(
await screen.queryByText('Documentation #2'),
).not.toBeInTheDocument();
expect(await screen.queryByTestId('doc-not-found')).not.toBeInTheDocument();
expect(screen.queryByText('Curated Documentation')).toBeInTheDocument();
expect(screen.queryByText('Documentation #1')).toBeInTheDocument();
expect(screen.queryByText('Documentation #2')).not.toBeInTheDocument();
expect(screen.queryByTestId('doc-not-found')).not.toBeInTheDocument();
});
it('should render nothing with filtering yielding no result', async () => {
@@ -163,16 +159,10 @@ describe('Entity List Docs Grid', () => {
},
);
expect(
await screen.queryByText('Curated Documentation'),
).not.toBeInTheDocument();
expect(
await screen.queryByText('Documentation #1'),
).not.toBeInTheDocument();
expect(
await screen.queryByText('Documentation #2'),
).not.toBeInTheDocument();
expect(await screen.queryByTestId('doc-not-found')).not.toBeInTheDocument();
expect(screen.queryByText('Curated Documentation')).not.toBeInTheDocument();
expect(screen.queryByText('Documentation #1')).not.toBeInTheDocument();
expect(screen.queryByText('Documentation #2')).not.toBeInTheDocument();
expect(screen.queryByTestId('doc-not-found')).not.toBeInTheDocument();
});
it('should render an error without any documentation and without filtering', async () => {
@@ -189,15 +179,9 @@ describe('Entity List Docs Grid', () => {
},
);
expect(
await screen.queryByText('All Documentation'),
).not.toBeInTheDocument();
expect(
await screen.queryByText('Documentation #1'),
).not.toBeInTheDocument();
expect(
await screen.queryByText('Documentation #2'),
).not.toBeInTheDocument();
expect(await screen.queryByTestId('doc-not-found')).toBeInTheDocument();
expect(screen.queryByText('All Documentation')).not.toBeInTheDocument();
expect(screen.queryByText('Documentation #1')).not.toBeInTheDocument();
expect(screen.queryByText('Documentation #2')).not.toBeInTheDocument();
expect(screen.queryByTestId('doc-not-found')).toBeInTheDocument();
});
});
+80 -5
View File
@@ -13990,10 +13990,10 @@ __metadata:
languageName: node
linkType: hard
"@types/semver@npm:^7.3.8":
version: 7.3.12
resolution: "@types/semver@npm:7.3.12"
checksum: 35536b2fc5602904f21cae681f6c9498e177dab3f54ae37c92f9a1b7e43c35f18bcd81e1c98c1cf0d33ee046bb06c771e9928c1c00a401d56a03f56549252a15
"@types/semver@npm:^7.3.12, @types/semver@npm:^7.3.8":
version: 7.3.13
resolution: "@types/semver@npm:7.3.13"
checksum: 00c0724d54757c2f4bc60b5032fe91cda6410e48689633d5f35ece8a0a66445e3e57fa1d6e07eb780f792e82ac542948ec4d0b76eb3484297b79bd18b8cf1cb0
languageName: node
linkType: hard
@@ -14446,6 +14446,16 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/scope-manager@npm:5.43.0":
version: 5.43.0
resolution: "@typescript-eslint/scope-manager@npm:5.43.0"
dependencies:
"@typescript-eslint/types": 5.43.0
"@typescript-eslint/visitor-keys": 5.43.0
checksum: e594c7a32c3fa29e46dd0b0bc62f97f154bd864682ae7da87a14b6f4336f4cb02f6ed0602bbdb15783e4230ecdf8a0ccc6f7c5820850e8f11240c9e4fb0e388d
languageName: node
linkType: hard
"@typescript-eslint/scope-manager@npm:5.9.0":
version: 5.9.0
resolution: "@typescript-eslint/scope-manager@npm:5.9.0"
@@ -14480,6 +14490,13 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/types@npm:5.43.0":
version: 5.43.0
resolution: "@typescript-eslint/types@npm:5.43.0"
checksum: fc5e5431c305feee4a3faae84f34df482e08d74b910a6f9376b01326c682ceefeeb0e270d03d7778787bc94ef05b3b85ee6d3c9d732290fbdb4a67ae1b110226
languageName: node
linkType: hard
"@typescript-eslint/types@npm:5.9.0":
version: 5.9.0
resolution: "@typescript-eslint/types@npm:5.9.0"
@@ -14505,6 +14522,24 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/typescript-estree@npm:5.43.0":
version: 5.43.0
resolution: "@typescript-eslint/typescript-estree@npm:5.43.0"
dependencies:
"@typescript-eslint/types": 5.43.0
"@typescript-eslint/visitor-keys": 5.43.0
debug: ^4.3.4
globby: ^11.1.0
is-glob: ^4.0.3
semver: ^7.3.7
tsutils: ^3.21.0
peerDependenciesMeta:
typescript:
optional: true
checksum: 3479f9413d73369ab3d574580c90a72f74d2ae1ec4afe485eebfad054c3d15c89f23a137bb9d6197dfdae33e444a76a99f6832688787feabbb064e09d39a3f55
languageName: node
linkType: hard
"@typescript-eslint/typescript-estree@npm:5.9.0":
version: 5.9.0
resolution: "@typescript-eslint/typescript-estree@npm:5.9.0"
@@ -14523,7 +14558,7 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/utils@npm:5.36.2, @typescript-eslint/utils@npm:^5.10.0":
"@typescript-eslint/utils@npm:5.36.2":
version: 5.36.2
resolution: "@typescript-eslint/utils@npm:5.36.2"
dependencies:
@@ -14539,6 +14574,24 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/utils@npm:^5.10.0, @typescript-eslint/utils@npm:^5.13.0":
version: 5.43.0
resolution: "@typescript-eslint/utils@npm:5.43.0"
dependencies:
"@types/json-schema": ^7.0.9
"@types/semver": ^7.3.12
"@typescript-eslint/scope-manager": 5.43.0
"@typescript-eslint/types": 5.43.0
"@typescript-eslint/typescript-estree": 5.43.0
eslint-scope: ^5.1.1
eslint-utils: ^3.0.0
semver: ^7.3.7
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
checksum: 4c6b383b51506b57230f2624f883ae21e5d8411d138587c04fe3145f915bf8c289cc2a9f7b0b3faba98345ba230504e5014922bcc578aa0badd594d9eaa8f9ef
languageName: node
linkType: hard
"@typescript-eslint/visitor-keys@npm:5.36.2":
version: 5.36.2
resolution: "@typescript-eslint/visitor-keys@npm:5.36.2"
@@ -14549,6 +14602,16 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/visitor-keys@npm:5.43.0":
version: 5.43.0
resolution: "@typescript-eslint/visitor-keys@npm:5.43.0"
dependencies:
"@typescript-eslint/types": 5.43.0
eslint-visitor-keys: ^3.3.0
checksum: 4820679e50096dcdaadc7c95d32e5dca3ba8510acf1a865e283822bae3940a2faec02ad8abe793f8a25f75b600f1e7215e1fd3b3ba73779eff737fa90d092550
languageName: node
linkType: hard
"@typescript-eslint/visitor-keys@npm:5.9.0":
version: 5.9.0
resolution: "@typescript-eslint/visitor-keys@npm:5.9.0"
@@ -20502,6 +20565,17 @@ __metadata:
languageName: node
linkType: hard
"eslint-plugin-testing-library@npm:^5.9.1":
version: 5.9.1
resolution: "eslint-plugin-testing-library@npm:5.9.1"
dependencies:
"@typescript-eslint/utils": ^5.13.0
peerDependencies:
eslint: ^7.5.0 || ^8.0.0
checksum: d09f9486945807e9587d52b6979117bc41b750df741567381a06219671096afb318696a0e0db63e253e150fead40e77ef9653ee00f1dda83fc8920e3b3c47107
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"
@@ -32907,6 +32981,7 @@ __metadata:
e2e-test: "workspace:*"
eslint: ^8.6.0
eslint-plugin-notice: ^0.9.10
eslint-plugin-testing-library: ^5.9.1
fs-extra: 10.1.0
husky: ^8.0.0
lint-staged: ^13.0.0