@testing-library/dom#waitFor TypeScript Examples
The following examples show how to use
@testing-library/dom#waitFor.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: ChatMessages.test.tsx From glific-frontend with GNU Affero General Public License v3.0 | 6 votes |
test('Should render for multi-search', async () => {
defineUrl('http://localhost:3000/chat/2?search=8');
const { getByTestId } = render(chatMessages);
await waitFor(() => {
const container: any = document.querySelector('.messageContainer');
fireEvent.scroll(container, { target: { scrollY: 0 } });
fireEvent.click(getByTestId('loadMoreMessages'));
});
});
Example #2
Source File: Setup.test.tsx From legend-studio with Apache License 2.0 | 6 votes |
test(
integrationTest('Disable project selector when there is no projects'),
async () => {
MOBX__enableSpyOrMock();
jest.spyOn(sdlcServerClient, 'getProjects').mockResolvedValue([]);
MOBX__disableSpyOrMock();
TEST__provideMockedWebApplicationNavigator();
const { queryByText } = render(
<MemoryRouter>
<TEST__ApplicationStoreProvider
config={TEST__getTestStudioConfig()}
pluginManager={LegendStudioPluginManager.create()}
>
<TEST__SDLCServerClientProvider>
<Setup />
</TEST__SDLCServerClientProvider>
</TEST__ApplicationStoreProvider>
</MemoryRouter>,
);
await waitFor(() =>
expect(
queryByText(
'You have no projects, please create or acquire access for at least one',
),
).not.toBeNull(),
);
},
);
Example #3
Source File: ChatMessages.test.tsx From glific-frontend with GNU Affero General Public License v3.0 | 6 votes |
// test('cancel after dialog box open', async () => {
// const { getByText, getByTestId } = render(chatMessages);
// await waitFor(() => {
// fireEvent.click(getByTestId('messageOptions'));
// fireEvent.click(getByTestId('dialogButton'));
// });
// fireEvent.click(getByText('Cancel'));
// });
// Need to first scroll up
test('click on Jump to latest', async () => {
const { getByTestId } = render(chatMessages);
const messageContainer: any = document.querySelector('.messageContainer');
await act(async () => {
await new Promise((r) => setTimeout(r, 1500));
});
fireEvent.scroll(messageContainer, { target: { scrollTop: 10 } });
await waitFor(() => {
fireEvent.click(getByTestId('jumpToLatest'));
});
});
Example #4
Source File: Select.test.tsx From chroma-react with MIT License | 6 votes |
test('it *does not* render errorMessage when not hasError', async () => {
const props = getBaseProps();
const { queryByText } = renderWithTheme(
<Select {...props} data-testid={testId} errorMessage="should not show up" />
);
await act(async () => {
await waitFor(() => {
expect(queryByText('should not show up')).not.toBeInTheDocument();
});
});
});
Example #5
Source File: cancel-token.ts From vue-concurrency with MIT License | 6 votes |
describe("getCancelToken", () => {
it("works", async () => {
const { promise, reject } = defer();
const signalMock = {
pr: promise,
} as AbortSignalWithPromise;
const cancelFn = jest.fn();
class CancelToken {
constructor(cb: (cancel: () => void) => void) {
cb(cancelFn);
}
}
const axiosMock = {
CancelToken,
};
getCancelToken(axiosMock, signalMock);
expect(cancelFn).not.toBeCalled();
reject("cancel");
await waitFor(() => expect(cancelFn).toHaveBeenCalled());
});
});
Example #6
Source File: NewFileWizard.test.tsx From pybricks-code with MIT License | 6 votes |
describe('cancel', () => {
it('should dispatch cancel when close button is clicked', async () => {
const [user, dialog, dispatch] = testRender(<NewFileWizard />, {
explorer: { newFileWizard: { isOpen: true } },
});
await user.click(dialog.getByRole('button', { name: 'Close' }));
expect(dispatch).toHaveBeenCalledWith(newFileWizardDidCancel());
});
it('should dispatch cancel when escape button is pressed', async () => {
const [user, dialog, dispatch] = testRender(<NewFileWizard />, {
explorer: { newFileWizard: { isOpen: true } },
});
await waitFor(() =>
expect(dialog.getByRole('textbox', { name: 'File name' })).toHaveFocus(),
);
// FIXME: use userEvent instead of fireEvent
// blocked by https://github.com/palantir/blueprint/pull/5349
// await user.keyboard('{Escape}');
user;
fireEvent.keyDown(document.activeElement ?? document, {
key: 'Escape',
keyCode: 27,
which: 27,
});
expect(dispatch).toHaveBeenCalledWith(newFileWizardDidCancel());
});
});
Example #7
Source File: task-multiple.ts From vue-concurrency with MIT License | 6 votes |
describe("useTask | multiple | task", () => {
test("can yield instance of another task", async () => {
await mockSetup(async () => {
const childTask = useTask(function* () {
yield wait(20);
return "foo";
});
const mainTask = useTask(function* () {
const a: YieldReturn<typeof childTask> = yield childTask.perform();
const b: YieldReturn<typeof childTask> = yield childTask.perform();
return a + b;
});
mainTask.perform();
await waitFor(() => expect(mainTask.last?.value).toBe("foofoo"));
});
});
test("task picks up thrown error of another task", async () => {
await mockSetup(async () => {
const error = new Error("Task error");
const childTask = useTask(function* () {
throw error;
});
const mainTask = useTask(function* () {
return yield childTask.perform();
});
mainTask.perform();
await waitFor(() => expect(mainTask.last?.error).toBe(error));
});
});
});
Example #8
Source File: NewFileWizard.test.tsx From pybricks-code with MIT License | 6 votes |
describe('accept', () => {
it('should dispatch accept action when button is clicked', async () => {
const [user, dialog, dispatch] = testRender(<NewFileWizard />, {
explorer: { newFileWizard: { isOpen: true } },
});
const button = dialog.getByLabelText('Create');
// have to type a file name before Create button is enabled
await user.type(dialog.getByRole('textbox', { name: 'File name' }), 'test');
await waitFor(() => expect(button).not.toBeDisabled());
await user.click(button);
expect(dispatch).toHaveBeenCalledWith(
newFileWizardDidAccept('test', '.py', Hub.Technic),
);
});
it('should dispatch accept action when enter is pressed ', async () => {
const [user, dialog, dispatch] = testRender(<NewFileWizard />, {
explorer: { newFileWizard: { isOpen: true } },
});
await user.type(
dialog.getByRole('textbox', { name: 'File name' }),
'test{Enter}',
);
expect(dispatch).toHaveBeenCalledWith(
newFileWizardDidAccept('test', '.py', Hub.Technic),
);
});
});
Example #9
Source File: index.test.tsx From oasis-wallet-web with Apache License 2.0 | 6 votes |
describe('<NetworkSelector />', () => {
let store: ReturnType<typeof configureAppStore>
beforeEach(() => {
store = configureAppStore()
})
it('should match snapshot', () => {
const component = renderComponent(store)
expect(component.container.firstChild).toMatchSnapshot()
})
it('should allow switching network', async () => {
const dispatchSpy = jest.spyOn(store, 'dispatch')
const component = renderComponent(store)
expect(component.queryByTestId('active-network')).toContainHTML('toolbar.networks.local')
userEvent.click(screen.getByTestId('network-selector'))
await waitFor(() => expect(screen.getByText('toolbar.networks.testnet')))
screen.getByText('toolbar.networks.testnet').click()
expect(dispatchSpy).toHaveBeenCalledWith({
payload: 'testnet',
type: 'network/selectNetwork',
})
})
})
Example #10
Source File: Snackbar.test.tsx From chroma-react with MIT License | 6 votes |
test('it renders a dismissible Snackbar', async () => {
const mockFn = jest.fn();
const { findByLabelText } = renderWithTheme(
<Snackbar {...getBaseProps()} allowDismiss onClose={mockFn} />
);
const button = await findByLabelText('Close Notification');
fireEvent.click(button);
await waitFor(() => expect(mockFn).toBeCalledTimes(1));
});
Example #11
Source File: ChatMessages.test.tsx From glific-frontend with GNU Affero General Public License v3.0 | 5 votes |
it('should have title as group name', async () => {
const { getByTestId } = render(chatMessagesWithCollection);
await waitFor(() => {
expect(getByTestId('beneficiaryName')).toHaveTextContent('Default Group');
});
});
Example #12
Source File: sagas.test.ts From pybricks-code with MIT License | 5 votes |
describe('handleShowAlert', () => {
let toaster: TestToaster;
let saga: AsyncSaga;
beforeEach(async () => {
toaster = new TestToaster();
jest.spyOn(toaster, 'show');
jest.spyOn(toaster, 'dismiss');
saga = new AsyncSaga(alerts, { toaster });
});
it('should show toast', async () => {
saga.put(
alertsShowAlert('alerts', 'unexpectedError', {
error: { name: 'TestError', message: 'test error' },
}),
);
expect(toaster.dismiss).not.toHaveBeenCalled();
expect(toaster.show).toHaveBeenCalled();
toaster.dismiss(toaster.getToasts().at(-1)?.key ?? '');
await expect(saga.take()).resolves.toEqual(
alertsDidShowAlert('alerts', 'unexpectedError', 'dismiss'),
);
});
it('should show close and re-open toast with same key', async () => {
// request to show the same alert twice
saga.put(
alertsShowAlert('alerts', 'unexpectedError', {
error: { name: 'TestError', message: 'test error' },
}),
);
saga.put(
alertsShowAlert('alerts', 'unexpectedError', {
error: { name: 'TestError', message: 'test error' },
}),
);
// at this point, show has only been called once to display the first alert
expect(toaster.show).toHaveBeenCalled();
// and then dismiss was called to close it
expect(toaster.dismiss).toHaveBeenCalled();
// which should result in an action
await expect(saga.take()).resolves.toEqual(
alertsDidShowAlert('alerts', 'unexpectedError', 'dismiss'),
);
// then after a delay, the second alert is shown
await waitFor(() => expect(toaster.show).toHaveBeenCalledTimes(2));
// then we dismiss it manually, like normal
toaster.dismiss(toaster.getToasts().at(-1)?.key ?? '');
// and get the action for the second dismiss
await expect(saga.take()).resolves.toEqual(
alertsDidShowAlert('alerts', 'unexpectedError', 'dismiss'),
);
});
afterEach(async () => {
await saga.end();
});
});
Example #13
Source File: ChatMessages.test.tsx From glific-frontend with GNU Affero General Public License v3.0 | 5 votes |
test('Load more messages', async () => {
const searchQuery = {
query: SEARCH_QUERY,
variables: {
filter: {},
contactOpts: { limit: DEFAULT_CONTACT_LIMIT },
messageOpts: { limit: DEFAULT_MESSAGE_LIMIT },
},
data: {
search: [
{
group: null,
contact: {
id: '2',
name: 'Effie Cormier',
phone: '987654321',
maskedPhone: '98****321',
lastMessageAt: '2020-06-29T09:31:47Z',
status: 'VALID',
fields: '{}',
bspStatus: 'SESSION_AND_HSM',
isOrgRead: true,
},
messages,
},
],
},
};
cache.writeQuery(searchQuery);
const client = new ApolloClient({
cache: cache,
assumeImmutableResults: true,
});
const chatMessages = (
<MemoryRouter>
<ApolloProvider client={client}>
<ChatMessages contactId="2" />
</ApolloProvider>
</MemoryRouter>
);
const { getByTestId } = render(chatMessages);
await waitFor(() => {
const container: any = document.querySelector('.messageContainer');
fireEvent.scroll(container, { target: { scrollY: 0 } });
fireEvent.click(getByTestId('loadMoreMessages'));
});
});
Example #14
Source File: RenameFileDialog.test.tsx From pybricks-code with MIT License | 5 votes |
describe('rename button', () => {
it('should accept the dialog Rename is clicked', async () => {
const [user, dialog, dispatch] = testRender(<RenameFileDialog />, {
explorer: { renameFileDialog: { isOpen: true, fileName: 'old.file' } },
});
const button = dialog.getByRole('button', { name: 'Rename' });
// have to type a new file name before Rename button is enabled
const input = dialog.getByLabelText('File name');
await waitFor(() => expect(input).toHaveFocus());
await user.type(input, 'new', { skipClick: true });
await waitFor(() => expect(button).not.toBeDisabled());
await user.click(button);
expect(dispatch).toHaveBeenCalledWith(
renameFileDialogDidAccept('old.file', 'new.file'),
);
});
it('should accept the dialog when enter is pressed in the text input', async () => {
const [user, dialog, dispatch] = testRender(<RenameFileDialog />, {
explorer: { renameFileDialog: { isOpen: true, fileName: 'old.file' } },
});
// have to type a new file name before Rename button is enabled
const input = dialog.getByLabelText('File name');
await waitFor(() => expect(input).toHaveFocus());
await user.type(input, 'new{Enter}', { skipClick: true });
expect(dispatch).toHaveBeenCalledWith(
renameFileDialogDidAccept('old.file', 'new.file'),
);
});
it('should be cancellable', async () => {
const [user, dialog, dispatch] = testRender(<RenameFileDialog />, {
explorer: { renameFileDialog: { isOpen: true } },
});
const button = dialog.getByRole('button', { name: 'Close' });
await waitFor(() => expect(button).toBeVisible());
await user.click(button);
expect(dispatch).toHaveBeenCalledWith(renameFileDialogDidCancel());
});
});
Example #15
Source File: QueryBuilder_Milestoning.test.tsx From legend-studio with Apache License 2.0 | 5 votes |
test(
integrationTest(
'Query builder state is properly set after processing a lambda with non-temporal source Business Temporal target',
),
async () => {
const pluginManager = LegendQueryPluginManager.create();
pluginManager.usePresets([new Query_GraphPreset()]).install();
const mockedQueryStore = TEST__provideMockedLegendQueryStore({
pluginManager,
});
const renderResult = await TEST__setUpQueryEditor(
mockedQueryStore,
TEST_MilestoningModel,
stub_RawLambda(),
'my::map',
'my::runtime',
);
const queryBuilderState = mockedQueryStore.queryBuilderState;
const _personClass =
mockedQueryStore.graphManagerState.graph.getClass('my::Firm');
act(() => {
queryBuilderState.changeClass(_personClass);
});
const queryBuilderSetup = await waitFor(() =>
renderResult.getByTestId(QUERY_BUILDER_TEST_ID.QUERY_BUILDER_SETUP),
);
await waitFor(() => getByText(queryBuilderSetup, 'Firm'));
await waitFor(() => getByText(queryBuilderSetup, 'map'));
await waitFor(() => getByText(queryBuilderSetup, 'runtime'));
act(() => {
queryBuilderState.initialize(
create_RawLambda(
TEST_DATA__simpleProjectionWithNonTemporalSourceAndBusinessTemporalTarget.parameters,
TEST_DATA__simpleProjectionWithNonTemporalSourceAndBusinessTemporalTarget.body,
),
);
});
const projectionColumnState = guaranteeType(
queryBuilderState.fetchStructureState.projectionState.columns[0],
QueryBuilderSimpleProjectionColumnState,
);
const derivedPropertyExpressionStates =
projectionColumnState.propertyExpressionState
.derivedPropertyExpressionStates;
// property replaced with derived property as it is milestoned
expect(derivedPropertyExpressionStates.length).toBe(1);
const parameterValues = guaranteeNonNullable(
derivedPropertyExpressionStates[0]?.propertyExpression.parametersValues,
);
// default milestoning date is propagated as date propagation is not supported.
expect(parameterValues.length).toBe(2);
},
);
Example #16
Source File: task-concurrency-restartable.ts From vue-concurrency with MIT License | 5 votes |
describe("useTask | restartable task", () => {
test("runs the first task instance right away", async () => {
await mockSetup(() => {
const task = useTask(function* () { }).restartable();
const taskInstance = task.perform();
expect(taskInstance.isRunning).toBe(true);
});
});
test("cancels first running task when the task is performed again", async () => {
await mockSetup(async () => {
const task = useTask(function* () {
yield wait(10);
}).restartable();
const taskInstance1 = task.perform();
await wait(5);
const taskInstance2 = task.perform();
expect(taskInstance1.isCanceling).toBe(true);
expect(taskInstance2.isRunning).toBe(true);
const taskInstance3 = task.perform();
expect(taskInstance2.isCanceling).toBe(true);
expect(taskInstance3.isRunning).toBe(true);
});
});
test("cancels first running task when maxConcurrency is reached", async () => {
await mockSetup(async () => {
const task = useTask(function* () {
yield wait(50);
})
.restartable()
.maxConcurrency(3);
const [instance1, instance2, instance3] = perform3x(task);
expect(instance1.isRunning).toBe(true);
expect(instance2.isRunning).toBe(true);
expect(instance3.isRunning).toBe(true);
const instance4 = task.perform();
expect(instance1.isCanceling).toBe(true);
expect(instance2.isRunning).toBe(true);
expect(instance3.isRunning).toBe(true);
expect(instance4.isRunning).toBe(true);
const instance5 = task.perform();
await waitFor(() => expect(instance2.isCanceling).toBe(true));
expect(instance3.isRunning).toBe(true);
expect(instance4.isRunning).toBe(true);
expect(instance5.isRunning).toBe(true);
});
});
});
Example #17
Source File: QueryBuilder_Milestoning.test.tsx From legend-studio with Apache License 2.0 | 5 votes |
test(
integrationTest(
'Query builder state is properly set after processing a lambda with non-temporal source BiTemporal target',
),
async () => {
const pluginManager = LegendQueryPluginManager.create();
pluginManager.usePresets([new Query_GraphPreset()]).install();
const mockedQueryStore = TEST__provideMockedLegendQueryStore({
pluginManager,
});
const renderResult = await TEST__setUpQueryEditor(
mockedQueryStore,
TEST_MilestoningModel,
stub_RawLambda(),
'my::map',
'my::runtime',
);
const queryBuilderState = mockedQueryStore.queryBuilderState;
const _personClass =
mockedQueryStore.graphManagerState.graph.getClass('my::Firm');
act(() => {
queryBuilderState.changeClass(_personClass);
});
const queryBuilderSetup = await waitFor(() =>
renderResult.getByTestId(QUERY_BUILDER_TEST_ID.QUERY_BUILDER_SETUP),
);
await waitFor(() => getByText(queryBuilderSetup, 'Firm'));
await waitFor(() => getByText(queryBuilderSetup, 'map'));
await waitFor(() => getByText(queryBuilderSetup, 'runtime'));
act(() => {
queryBuilderState.initialize(
create_RawLambda(
TEST_DATA__simpleProjectionWithNonTemporalSourceAndBiTemporalTarget.parameters,
TEST_DATA__simpleProjectionWithNonTemporalSourceAndBiTemporalTarget.body,
),
);
});
const projectionColumnState = guaranteeType(
queryBuilderState.fetchStructureState.projectionState.columns[0],
QueryBuilderSimpleProjectionColumnState,
);
const derivedPropertyExpressionStates =
projectionColumnState.propertyExpressionState
.derivedPropertyExpressionStates;
// property replaced with derived property as it is milestoned
expect(derivedPropertyExpressionStates.length).toBe(1);
const parameterValues = guaranteeNonNullable(
derivedPropertyExpressionStates[0]?.propertyExpression.parametersValues,
);
// default milestoning date is propagated as date propagation is not supported.
expect(parameterValues.length).toBe(3);
},
);
Example #18
Source File: task-cancel.ts From vue-concurrency with MIT License | 4 votes |
describe("useTask cancel", () => {
test("taskInstance.cancel results in isCanceled:true and no value", async () => {
let reached2ndYield = false;
await mockSetup(async () => {
const task = useTask(function* () {
yield wait(15);
reached2ndYield = true;
return "foo";
});
const taskInstance = task.perform();
expect(taskInstance.isRunning).toBe(true);
taskInstance.cancel();
expect(taskInstance.isCanceling).toBe(true);
await waitFor(() => expect(taskInstance.isCanceled).toBe(true), {
interval: 10,
});
expect(taskInstance.isFinished).toBe(true);
expect(taskInstance.isRunning).toBe(false);
expect(taskInstance.isError).toBe(false);
expect(taskInstance.isSuccessful).toBe(false);
expect(taskInstance.value).toBe(null);
expect(reached2ndYield).toBe(false);
});
});
test("task.cancelAll cancels all running instances", async () => {
await mockSetup(async () => {
const task = useTask(function* () {
return "foo";
});
const taskInstance1 = task.perform();
const taskInstance2 = task.perform();
try {
await taskInstance1;
await taskInstance2;
} catch (e) {
expect(e).toBe("cancel");
}
const taskInstance3 = task.perform();
const taskInstance4 = task.perform();
task.cancelAll();
expect(taskInstance1.isCanceled).toBe(false);
expect(taskInstance2.isCanceled).toBe(false);
await waitFor(() => expect(taskInstance3.isCanceled).toBe(true));
expect(taskInstance4.isCanceled).toBe(true);
});
});
test("task.cancelAll with force works", async () => {
await mockSetup(async () => {
const task = useTask(function* () {
return "foo";
});
task.perform();
task.perform();
task.cancelAll({ force: true });
});
});
test("signal.pr is called when the task is canceled", async () => {
const signalCatchCallback = jest.fn();
await mockSetup(async () => {
const task = useTask(function* (signal) {
signal.pr.catch(signalCatchCallback);
yield wait(30);
return "foo";
});
const taskInstance = task.perform();
await wait(5);
taskInstance.cancel();
await waitFor(() => expect(taskInstance.isFinished).toBe(true));
expect(signalCatchCallback).toHaveBeenCalled();
});
});
});
Example #19
Source File: ModelProvider.test.tsx From aem-react-editable-components with Apache License 2.0 | 4 votes |
describe('ModelProvider ->', () => {
const TEST_PAGE_PATH = '/page/jcr:content/root';
const ROOT_NODE_CLASS_NAME = 'root-class';
const INNER_COMPONENT_ID = 'innerContent';
const TEST_COMPONENT_MODEL = { ':type': 'test/components/componentchild' };
let rootNode: any;
/**
* React warn if a non-standard DOM attribute is used on a native DOM node.
*
* When the HTML div element is wrapped to be a React Component it is no longer a DOM node and camelCase properties
* can be passed to props.
*
* If instead of the <ModelProvider><Dummy /></ModelProvider> the <ModelProvider><div /></ModelProvider> notation
* is used, the following error might be shown in the browser console:
*
* Warning: React does not recognize the `camelCaseProp` prop on a DOM element. If you intentionally want it to
* appear in the DOM as a custom attribute, spell it as lowercase `camelcaseprop` instead. If you accidentally
* passed it from a parent component, remove it from the DOM element.
* in div (created by ModelProvider)
* in ModelProvider
*
* for every camelCase property passed in props.
*
* See also: https://github.com/facebook/react/issues/10590
*/
interface DummyProps extends MappedComponentProperties{
className: string
}
class Dummy extends Component<DummyProps> {
render() {
return <div id={INNER_COMPONENT_ID} className={this.props.className}>Dummy</div>;
}
}
let addListenerSpy: jest.SpyInstance;
let getDataSpy: jest.SpyInstance;
beforeEach(() => {
addListenerSpy = jest.spyOn(ModelManager, 'addListener').mockImplementation();
getDataSpy = jest.spyOn(ModelManager, 'getData').mockResolvedValue(TEST_COMPONENT_MODEL);
rootNode = document.createElement('div');
rootNode.className = ROOT_NODE_CLASS_NAME;
document.body.appendChild(rootNode);
});
afterEach(() => {
if (rootNode) {
document.body.removeChild(rootNode);
}
});
describe('Tag instantiation ->', () => {
beforeEach(() => {
addListenerSpy.mockReset();
});
it('should initialize properly without parameter', () => {
// @ts-expect-error
ReactDOM.render(<ModelProvider wrappedComponent={Dummy}></ModelProvider>, rootNode);
expect(addListenerSpy).toHaveBeenCalledWith('', expect.any(Function));
const childNode = rootNode.querySelector('#' + INNER_COMPONENT_ID);
expect(childNode).toBeDefined();
});
it('should initialize properly with a path parameter', () => {
ReactDOM.render(<ModelProvider cqPath={TEST_PAGE_PATH} wrappedComponent={Dummy}></ModelProvider>, rootNode);
expect(addListenerSpy).toHaveBeenCalledWith(TEST_PAGE_PATH, expect.any(Function));
const childNode = rootNode.querySelector('#' + INNER_COMPONENT_ID);
expect(childNode).toBeDefined();
});
});
describe('Get data ->', () => {
beforeEach(() => {
getDataSpy.mockReset();
addListenerSpy.mockReset();
});
it('should subscribe on the data with undefined parameters', () => {
getDataSpy.mockResolvedValue({});
// @ts-expect-error
ReactDOM.render(<ModelProvider wrappedComponent={Dummy}></ModelProvider>, rootNode);
expect(addListenerSpy).toHaveBeenCalledWith('', expect.any(Function));
});
it('should subscribe on the data with the provided attributes', () => {
getDataSpy.mockResolvedValue({});
ReactDOM.render(<ModelProvider cqPath={TEST_PAGE_PATH} cqForceReload={true} wrappedComponent={Dummy}></ModelProvider>, rootNode);
expect(addListenerSpy).toHaveBeenCalledWith(TEST_PAGE_PATH, expect.any(Function));
});
});
describe('withModel ->', () => {
beforeEach(() => {
addListenerSpy.mockReset();
});
it('should initialize properly without parameter', () => {
const DummyWithModel: any = withModel(Dummy);
ReactDOM.render(<DummyWithModel></DummyWithModel>, rootNode);
expect(addListenerSpy).toHaveBeenCalledWith('', expect.any(Function));
const childNode = rootNode.querySelector('#' + INNER_COMPONENT_ID);
expect(childNode).toBeDefined();
});
it('should initialize properly with a path parameter', () => {
const DummyWithModel = withModel(Dummy);
// @ts-ignore
ReactDOM.render(<DummyWithModel cqPath={TEST_PAGE_PATH}></DummyWithModel>, rootNode);
expect(addListenerSpy).toHaveBeenCalledWith(TEST_PAGE_PATH, expect.any(Function));
const childNode = rootNode.querySelector('#' + INNER_COMPONENT_ID);
expect(childNode).toBeDefined();
});
it('should render a subpage properly when page path is provided', () => {
const DummyWithModel = withModel(Dummy, { injectPropsOnInit: true });
// @ts-ignore
ReactDOM.render(<DummyWithModel pagePath={TEST_PAGE_PATH}></DummyWithModel>, rootNode);
expect(getDataSpy).toHaveBeenCalledWith({ path: TEST_PAGE_PATH, forceReload: false });
const childNode = rootNode.querySelector('#' + INNER_COMPONENT_ID);
expect(childNode).toBeDefined();
});
it('should render components properly when component cqPath is provided', () => {
const DummyWithModel = withModel(Dummy, { injectPropsOnInit: true });
// @ts-ignore
ReactDOM.render(<DummyWithModel cqPath={TEST_PAGE_PATH}></DummyWithModel>, rootNode);
expect(getDataSpy).toHaveBeenCalledWith({ path: TEST_PAGE_PATH, forceReload: false });
const childNode = rootNode.querySelector('#' + INNER_COMPONENT_ID);
expect(childNode).toBeDefined();
});
it('should render components properly when containing page path and path to item is provided', () => {
addListenerSpy = jest.spyOn(ModelManager, 'addListener').mockImplementationOnce((path, callback) => {
callback();
});
const PAGE_PATH = '/page/subpage';
const ITEM_PATH = 'root/paragraph';
const DummyWithModel = withModel(Dummy, { injectPropsOnInit: true });
// @ts-ignore
ReactDOM.render(<DummyWithModel pagePath={PAGE_PATH} itemPath={ITEM_PATH}></DummyWithModel>, rootNode);
expect(addListenerSpy).toHaveBeenCalled();
expect(getDataSpy).toHaveBeenCalledWith({
path: `${PAGE_PATH}/jcr:content/${ITEM_PATH}`,
forceReload: false
});
const childNode = rootNode.querySelector('#' + INNER_COMPONENT_ID);
expect(childNode).toBeDefined();
});
it('should log error when there is no data', async () => {
// given
const error = new Error('404 - Not found');
getDataSpy.mockRejectedValue(error);
console.log = jest.fn();
const DummyWithModel = withModel(Dummy, { injectPropsOnInit: true });
// when
// @ts-ignore
ReactDOM.render(<DummyWithModel cqPath={TEST_PAGE_PATH} ></DummyWithModel>, rootNode);
// then
await waitFor(() => expect(console.log).toHaveBeenCalledWith(error));
});
it('should fire event to reload editables when in editor', async () => {
const dispatchEventSpy: jest.SpyInstance =
jest.spyOn(PathUtils, 'dispatchGlobalCustomEvent').mockImplementation();
const isInEditor:jest.SpyInstance = jest.spyOn(Utils, 'isInEditor').mockImplementation(() => true);
const DummyWithModel = withModel(Dummy, { injectPropsOnInit: true });
// @ts-ignore
ReactDOM.render(<DummyWithModel pagePath={TEST_PAGE_PATH}></DummyWithModel>, rootNode);
expect(getDataSpy).toHaveBeenCalledWith({ path: TEST_PAGE_PATH, forceReload: false });
const childNode = rootNode.querySelector('#' + INNER_COMPONENT_ID);
expect(childNode).toBeDefined();
await waitFor(() =>
expect(dispatchEventSpy).toHaveBeenCalledWith(Constants.ASYNC_CONTENT_LOADED_EVENT, {})
);
isInEditor.mockReset();
dispatchEventSpy.mockReset();
});
});
describe('Unmount -> ', () => {
it('should remove listeners on unmount', () => {
const removeListenerSpy: jest.SpyInstance = jest.spyOn(ModelManager, 'removeListener').mockImplementation();
ReactDOM.render(<ModelProvider cqPath={TEST_PAGE_PATH} wrappedComponent={Dummy}></ModelProvider>, rootNode);
ReactDOM.unmountComponentAtNode(rootNode);
expect(removeListenerSpy).toHaveBeenCalledWith(TEST_PAGE_PATH, expect.any(Function));
});
});
});
Example #20
Source File: useAsyncResource.test.ts From use-async-resource with ISC License | 4 votes |
describe('useAsyncResource', () => {
const apiFn = (id: number) => Promise.resolve({ id, name: 'test name' });
const apiSimpleFn = () => Promise.resolve({ message: 'success' });
const apiFailingFn = () => Promise.reject({ message: 'error' });
afterEach(() => {
resourceCache(apiFn).clear();
resourceCache(apiSimpleFn).clear();
resourceCache(apiFailingFn).clear();
});
it('should create a new data reader', async () => {
// get the data reader from the custom hook, with params
const { result } = renderHook(() => useAsyncResource(apiFn, 1));
const [dataReader] = result.current;
// wait for it to fulfill
await suspendFor(dataReader);
// should be able to get raw data from the data reader
expect(dataReader()).toStrictEqual({ id: 1, name: 'test name' });
// same for api functions without params
const { result: simpleResult } = renderHook(() => useAsyncResource(apiSimpleFn, []));
const [simpleData] = simpleResult.current;
await suspendFor(simpleData);
expect(simpleData()).toStrictEqual({ message: 'success' });
});
it('should throw an error', async () => {
const { result } = renderHook(() => useAsyncResource(apiFailingFn, []));
const [dataReader] = result.current;
// wait for it to fulfill
await suspendFor(dataReader);
expect(dataReader).toThrowError(Error('error'));
});
it('should trigger an update for the data reader', async () => {
// get the data reader and the updater function from the custom hook
const { result } = renderHook(() => useAsyncResource(apiFn, 1));
const [dataReader, updateDataReader] = result.current;
// wait for it to fulfill
await suspendFor(dataReader);
// make sure we're able to get raw data from it
expect(dataReader(u => u.id)).toStrictEqual(1);
// call the updater function with new params
act(() => updateDataReader(2));
// this should generate a brand new data reader
const [newDataReader] = result.current;
// we will need to wait for its fulfillment
await suspendFor(newDataReader);
// check that it's indeed a new one
expect(newDataReader).not.toStrictEqual(dataReader);
// and that it returns different data
expect(newDataReader(u => u.id)).toStrictEqual(2);
});
it('should reuse a cached data reader', async () => {
// get the data reader and the updater function from the custom hook
const { result } = renderHook(() => useAsyncResource(apiFn, 1));
const [dataReader, updateDataReader] = result.current;
// wait for it to fulfill
await suspendFor(dataReader);
// call the updater function with new params
act(() => updateDataReader(2));
// this should generate a brand new data reader
const [newDataReader] = result.current;
// we will need to wait for its fulfillment
await suspendFor(newDataReader);
// call the updater one more time, but with the previous param
act(() => updateDataReader(1));
// the new data reader should use the previously cached version
const [cachedDataReader] = result.current;
// so nothing to wait for
expect(cachedDataReader).not.toThrow();
// make sure it's the exact same as the very first one
expect(cachedDataReader).toStrictEqual(dataReader);
// and that it returns the same data
expect(cachedDataReader(u => u.id)).toStrictEqual(1);
});
it('should create a lazy data reader', async () => {
// initialize a lazy data reader
const { result } = renderHook(() => useAsyncResource(apiFn));
const [dataReader, updateDataReader] = result.current;
// it should be available immediately, but should return `undefined`
expect(dataReader).not.toThrow();
expect(dataReader()).toStrictEqual(undefined);
// triggering an api call
act(() => updateDataReader(1));
const [updatedDataReader] = result.current;
// requires waiting for a fulfillment
await suspendFor(updatedDataReader);
// finally, we should have some data available
expect(updatedDataReader(u => u.id)).toStrictEqual(1);
});
it('should call the api function again if the cache is cleared', async () => {
// get the data reader and the updater function from the custom hook
const { result } = renderHook(() => useAsyncResource(apiFn, 1));
const [dataReader, updateDataReader] = result.current;
await suspendFor(dataReader);
// clear the cache before calling the updater with the previous param
resourceCache(apiFn).delete(1);
// call the updater function with same params
act(() => updateDataReader(1));
// this should generate a brand new data reader
const [newDataReader] = result.current;
// and we will need to wait for its fulfillment
await suspendFor(newDataReader);
// make sure it's different than the first one
expect(newDataReader).not.toStrictEqual(dataReader);
// but that it returns the same data
expect(newDataReader(u => u.id)).toStrictEqual(1);
});
it('should trigger new api calls if the params of the hook change', async () => {
// get the data reader and the updater function, injecting a prop that we'll update later
const { result, rerender } = renderHook(
({ paramId }) => useAsyncResource(apiFn, paramId),
{ initialProps: { paramId: 1 }},
);
// check that it suspends and it resolves with the expected data
let [dataReader] = result.current;
await suspendFor(dataReader);
expect(dataReader()).toStrictEqual({ id: 1, name: 'test name' });
// re-render with new props
rerender({ paramId: 2 });
// check that it suspends again and renders with new data
const [newDataReader] = result.current;
await suspendFor(newDataReader);
expect(newDataReader()).toStrictEqual({ id: 2, name: 'test name' });
});
it('should persist the data reader between renders - for api function with params', async () => {
// get the data reader and the updater function
const { result, rerender } = renderHook(
({ paramId }) => useAsyncResource(apiFn, paramId),
{ initialProps: { paramId: 1 }},
);
// check that it suspends and it resolves with the expected data
let [dataReader] = result.current;
await suspendFor(dataReader);
expect(dataReader()).toStrictEqual({ id: 1, name: 'test name' });
// re-render with same props
rerender({ paramId: 1 });
// check that it doesn't suspend again and the data reader is reused
const [newDataReader] = result.current;
expect(newDataReader).toStrictEqual(dataReader);
});
it('should persist the data reader between renders - for api function without params', async () => {
// get the data reader and the updater function
const { result, rerender } = renderHook(() => useAsyncResource(apiSimpleFn, []));
// check that it suspends and it resolves with the expected data
let [dataReader] = result.current;
await suspendFor(dataReader);
expect(dataReader()).toStrictEqual({ message: 'success' });
// render again
rerender();
// check that it doesn't suspend again and the data reader is reused
const [newDataReader] = result.current;
expect(newDataReader()).toStrictEqual(dataReader());
// expect(newDataReader).toStrictEqual(dataReader);
});
it('should preload a resource before rendering', async () => {
// start preloading the resource
preloadResource(apiSimpleFn);
// expect the resource to load faster than the component that will consume it
const preloadedResource = resourceCache(apiSimpleFn).get();
if (preloadedResource) {
await waitFor(() => preloadedResource());
}
// a component consuming the preloaded resource should have the data readily available
const { result } = renderHook(() => useAsyncResource(apiSimpleFn, []));
let [dataReader] = result.current;
expect(dataReader()).toStrictEqual({ message: 'success' });
});
});
Example #21
Source File: authorizer.test.tsx From hub with Apache License 2.0 | 4 votes |
describe('authorizer', () => {
afterEach(() => {
jest.resetAllMocks();
});
it("does't call to getUserAllowedActions when selectedOrg is undefined", async () => {
authorizer.init();
await waitFor(() => {
expect(API.getUserAllowedActions).toHaveBeenCalledTimes(0);
});
});
it('calls to getUserAllowedActions when selectedOrg is defined', async () => {
mocked(API).getUserAllowedActions.mockResolvedValue(allActions);
authorizer.init('org1');
await waitFor(() => {
expect(API.getUserAllowedActions).toHaveBeenCalledTimes(1);
expect(API.getUserAllowedActions).toHaveBeenCalledWith('org1');
});
});
it('calls onCompletion', async () => {
mocked(API).getUserAllowedActions.mockResolvedValue(allActions);
authorizer.init('org1');
authorizer.getAllowedActionsList(onCompletionMock);
await waitFor(() => {
expect(API.getUserAllowedActions).toHaveBeenCalledTimes(2);
expect(API.getUserAllowedActions).toHaveBeenLastCalledWith('org1');
expect(onCompletionMock).toHaveBeenCalledTimes(1);
});
});
describe('to update context', () => {
it('calls again to getUserAllowedActions when a new org is defined', async () => {
mocked(API).getUserAllowedActions.mockResolvedValue(allActions);
authorizer.init('org1');
await waitFor(() => {
expect(API.getUserAllowedActions).toHaveBeenCalledWith('org1');
});
authorizer.updateCtx('org2');
await waitFor(() => {
expect(API.getUserAllowedActions).toHaveBeenCalledTimes(2);
expect(API.getUserAllowedActions).toHaveBeenLastCalledWith('org2');
});
});
it('does not call getUserAllowedActions again when selected org is the same', async () => {
mocked(API).getUserAllowedActions.mockResolvedValue(allActions);
authorizer.init('org1');
await waitFor(() => {
expect(API.getUserAllowedActions).toHaveBeenCalledWith('org1');
});
authorizer.updateCtx('org1');
await waitFor(() => {
expect(API.getUserAllowedActions).toHaveBeenCalledTimes(1);
});
});
it('does not call getUserAllowedActions when not selected org', async () => {
mocked(API).getUserAllowedActions.mockResolvedValue(allActions);
authorizer.init('org1');
await waitFor(() => {
expect(API.getUserAllowedActions).toHaveBeenCalledWith('org1');
});
authorizer.updateCtx();
await waitFor(() => {
expect(API.getUserAllowedActions).toHaveBeenCalledTimes(1);
});
});
it('calls only one getUserAllowedActions when a new org is selected and previously not selected org', async () => {
mocked(API).getUserAllowedActions.mockResolvedValue(allActions);
authorizer.init();
authorizer.updateCtx('org1');
await waitFor(() => {
expect(API.getUserAllowedActions).toHaveBeenCalledTimes(1);
expect(API.getUserAllowedActions).toHaveBeenCalledWith('org1');
});
});
});
describe('check authorizated actions', () => {
it('calls getUserAllowedActions when selected org is different to saved one', async () => {
mocked(API).getUserAllowedActions.mockResolvedValue(allActions);
authorizer.init('org1');
await waitFor(() => {
expect(API.getUserAllowedActions).toHaveBeenCalledTimes(1);
expect(API.getUserAllowedActions).toHaveBeenCalledWith('org1');
});
authorizer.check({
action: AuthorizerAction.DeleteOrganization,
organizationName: 'org2',
user: 'user1',
});
await waitFor(() => {
expect(API.getUserAllowedActions).toHaveBeenCalledTimes(2);
expect(API.getUserAllowedActions).toHaveBeenLastCalledWith('org2');
});
});
it('returns true when all actions are allowed', async () => {
mocked(API).getUserAllowedActions.mockResolvedValue(allActions);
authorizer.init('org1');
await waitFor(() => {
expect(API.getUserAllowedActions).toHaveBeenCalledTimes(1);
expect(API.getUserAllowedActions).toHaveBeenCalledWith('org1');
});
const checked = authorizer.check({
action: AuthorizerAction.DeleteOrganization,
user: 'user1',
});
expect(checked).toBeTruthy();
});
it('returns true when action is allowed', async () => {});
it('returns false when action is not allowed', async () => {});
});
});
Example #22
Source File: dxc-date-input.component.spec.ts From halstack-angular with Apache License 2.0 | 4 votes |
describe("DxcDate", () => {
const newMockDate = new Date("1995/12/03");
const newValue = "03-12-1995";
test("should render dxc-date", async () => {
const { getByText } = await render(DxcDateInputComponent, {
componentProperties: { label: "test-date" },
imports: [
MatDayjsDateModule,
MatNativeDateModule,
MatInputModule,
MatDatepickerModule,
MdePopoverModule,
DxcBoxModule,
CommonModule,
DxcTextInputModule,
],
providers: [
{ provide: MAT_DATE_FORMATS, useValue: DAYJS_DATE_FORMATS },
{
provide: DateAdapter,
useClass: DayjsDateAdapter,
deps: [MAT_DATE_LOCALE, Platform],
},
],
});
expect(getByText("test-date"));
});
test("The input´s value is the same as the one received as a parameter", async () => {
const onChange = jest.fn();
const onBlur = jest.fn();
await render(DxcDateInputComponent, {
componentProperties: {
label: "test-input",
value: "03-12-1995",
onChange: {
emit: onChange,
} as any,
onBlur: {
emit: onBlur,
} as any,
},
imports: [
MatDayjsDateModule,
MatNativeDateModule,
MatInputModule,
MatDatepickerModule,
MdePopoverModule,
DxcBoxModule,
CommonModule,
DxcTextInputModule,
],
providers: [
{ provide: MAT_DATE_FORMATS, useValue: DAYJS_DATE_FORMATS },
{
provide: DateAdapter,
useClass: DayjsDateAdapter,
deps: [MAT_DATE_LOCALE, Platform],
},
],
});
const input = <HTMLInputElement>screen.getByRole("textbox");
const calendarIcon = screen.getByRole("calendarIcon");
input.focus();
expect(screen.getByDisplayValue("03-12-1995"));
fireEvent.click(calendarIcon);
expect(screen.getByText("DECEMBER 1995"));
expect(
screen.getByText("3").classList.contains("mat-calendar-body-selected")
).toBeTruthy();
});
test("dxc-date value change and default format", async () => {
const onChange = jest.fn();
await render(DxcDateInputComponent, {
componentProperties: {
label: "test-input",
onChange: {
emit: onChange,
} as any,
},
imports: [
MatDayjsDateModule,
MatNativeDateModule,
MatInputModule,
MatDatepickerModule,
MdePopoverModule,
DxcBoxModule,
CommonModule,
DxcTextInputModule,
],
providers: [
{ provide: MAT_DATE_FORMATS, useValue: DAYJS_DATE_FORMATS },
{
provide: DateAdapter,
useClass: DayjsDateAdapter,
deps: [MAT_DATE_LOCALE, Platform],
},
],
});
const input = <HTMLInputElement>screen.getByRole("textbox");
input.focus();
fireEvent.input(input, { target: { value: newValue } });
expect(onChange).toHaveBeenCalledWith({
value: newValue,
error: undefined,
date: newMockDate,
});
expect(screen.getByDisplayValue(newValue));
});
test("dxc-date change value twice as uncontrolled", async () => {
const onChange = jest.fn();
await render(DxcDateInputComponent, {
componentProperties: {
label: "test-input",
defaultValue: "22-10-1998",
onChange: {
emit: onChange,
} as any,
},
imports: [
MatDayjsDateModule,
MatNativeDateModule,
MatInputModule,
MatDatepickerModule,
MdePopoverModule,
DxcBoxModule,
CommonModule,
DxcTextInputModule,
],
providers: [
{ provide: MAT_DATE_FORMATS, useValue: DAYJS_DATE_FORMATS },
{
provide: DateAdapter,
useClass: DayjsDateAdapter,
deps: [MAT_DATE_LOCALE, Platform],
},
],
});
expect(screen.getByDisplayValue("22-10-1998"));
const input = <HTMLInputElement>screen.getByRole("textbox");
input.focus();
fireEvent.input(input, { target: { value: newValue } });
expect(onChange).toHaveBeenCalledWith({
value: newValue,
error: undefined,
date: newMockDate,
});
expect(screen.getByDisplayValue(newValue));
input.focus();
fireEvent.input(input, { target: { value: "04-10-1996" } });
expect(onChange).toHaveBeenCalledWith({
value: "04-10-1996",
error: undefined,
date: new Date("1996/10/04"),
});
expect(screen.getByDisplayValue("04-10-1996"));
});
test("Calendar´s value is the same as the input´s date if it´s right (Depending on the format)", async () => {
const onChange = jest.fn();
const onBlur = jest.fn();
await render(DxcDateInputComponent, {
componentProperties: {
label: "test-input",
format: "YYYY/MM/DD",
onChange: {
emit: onChange,
} as any,
onBlur: {
emit: onBlur,
} as any,
},
imports: [
MatDayjsDateModule,
MatNativeDateModule,
MatInputModule,
MatDatepickerModule,
MdePopoverModule,
DxcBoxModule,
CommonModule,
DxcTextInputModule,
],
providers: [
{ provide: MAT_DATE_FORMATS, useValue: DAYJS_DATE_FORMATS },
{
provide: DateAdapter,
useClass: DayjsDateAdapter,
deps: [MAT_DATE_LOCALE, Platform],
},
],
});
const input = <HTMLInputElement>screen.getByRole("textbox");
const calendarIcon = screen.getByRole("calendarIcon");
input.focus();
fireEvent.input(input, { target: { value: "1995/12/03" } });
expect(onChange).toHaveBeenCalledWith({
value: "1995/12/03",
error: undefined,
date: newMockDate,
});
input.focus();
expect(screen.getByDisplayValue("1995/12/03"));
fireEvent.click(calendarIcon);
waitFor(() => {
expect(screen.getByText("DECEMBER 1995"));
});
waitFor(() => {
expect(
screen.getByText("3").classList.contains("mat-calendar-body-selected")
).toBeTruthy();
});
});
test("dxc-date invalid value", async () => {
const onChange = jest.fn();
const invalidValue = "03-12-199_";
await render(DxcDateInputComponent, {
componentProperties: {
label: "test-input",
onChange: {
emit: onChange,
} as any,
},
imports: [
MatDayjsDateModule,
MatNativeDateModule,
MatInputModule,
MatDatepickerModule,
MdePopoverModule,
DxcBoxModule,
CommonModule,
DxcTextInputModule,
],
providers: [
{ provide: MAT_DATE_FORMATS, useValue: DAYJS_DATE_FORMATS },
{
provide: DateAdapter,
useClass: DayjsDateAdapter,
deps: [MAT_DATE_LOCALE, Platform],
},
],
});
const input = <HTMLInputElement>screen.getByRole("textbox");
input.focus();
fireEvent.input(input, { target: { value: invalidValue } });
expect(onChange).toHaveBeenCalledWith({
value: invalidValue,
error: undefined,
date: undefined,
});
});
test("onChange function is called when the user selects from the calendar", async () => {
const onChange = jest.fn();
await render(DxcDateInputComponent, {
componentProperties: {
label: "test-input",
value: newValue,
onChange: {
emit: onChange,
} as any,
},
imports: [
MatDayjsDateModule,
MatNativeDateModule,
MatInputModule,
MatDatepickerModule,
MdePopoverModule,
DxcBoxModule,
CommonModule,
DxcTextInputModule,
],
providers: [
{ provide: MAT_DATE_FORMATS, useValue: DAYJS_DATE_FORMATS },
{
provide: DateAdapter,
useClass: DayjsDateAdapter,
deps: [MAT_DATE_LOCALE, Platform],
},
],
});
const calendarIcon = screen.getByRole("calendarIcon");
fireEvent.click(calendarIcon);
fireEvent.click(screen.getByText("4"));
waitFor(() => {
expect(onChange).toHaveBeenCalledWith({
value: "04-12-1995",
date: new Date("04/12/1995"),
});
});
});
test("onChange function is called when the user selects from the calendar, the stringValue received by the function is the date with the correct format", async () => {
const onChange = jest.fn();
await render(DxcDateInputComponent, {
componentProperties: {
label: "test-input",
value: "12-03-1995",
format: "MM-DD-YYYY",
onChange: {
emit: onChange,
} as any,
},
imports: [
MatDayjsDateModule,
MatNativeDateModule,
MatInputModule,
MatDatepickerModule,
MdePopoverModule,
DxcBoxModule,
CommonModule,
DxcTextInputModule,
],
providers: [
{ provide: MAT_DATE_FORMATS, useValue: DAYJS_DATE_FORMATS },
{
provide: DateAdapter,
useClass: DayjsDateAdapter,
deps: [MAT_DATE_LOCALE, Platform],
},
],
});
const calendarIcon = screen.getByRole("calendarIcon");
fireEvent.click(calendarIcon);
expect(screen.getByText("DECEMBER 1995"));
expect(
screen.getByText("3").classList.contains("mat-calendar-body-selected")
).toBeTruthy();
fireEvent.click(screen.getByText("4"));
waitFor(() => {
expect(onChange).toHaveBeenCalledWith({
value: "12-04-1995",
date: new Date("04/12/1995"),
});
});
});
test("If the user types something, if controlled and without onChange, the value doesn´t change", async () => {
const onChange = jest.fn();
await render(DxcDateInputComponent, {
componentProperties: {
label: "test-input",
value: newValue,
onChange: {
emit: onChange,
} as any,
},
imports: [
MatDayjsDateModule,
MatNativeDateModule,
MatInputModule,
MatDatepickerModule,
MdePopoverModule,
DxcBoxModule,
CommonModule,
DxcTextInputModule,
],
providers: [
{ provide: MAT_DATE_FORMATS, useValue: DAYJS_DATE_FORMATS },
{
provide: DateAdapter,
useClass: DayjsDateAdapter,
deps: [MAT_DATE_LOCALE, Platform],
},
],
});
const calendarIcon = screen.getByRole("calendarIcon");
fireEvent.click(calendarIcon);
expect(screen.getByText("DECEMBER 1995"));
expect(
screen.getByText("3").classList.contains("mat-calendar-body-selected")
).toBeTruthy();
fireEvent.click(screen.getByText("4"));
waitFor(() => {
expect(onChange).toHaveBeenCalledWith({
value: "04-12-1995",
date: new Date("04/12/1995"),
});
});
fireEvent.click(calendarIcon);
expect(screen.getByText("DECEMBER 1995"));
waitFor(() => {
expect(
screen.getByText("3").classList.contains("mat-calendar-body-selected")
).toBeTruthy();
});
});
test("controlled dxc-date", async () => {
const onChange = jest.fn();
const onBlur = jest.fn();
await render(DxcDateInputComponent, {
componentProperties: {
label: "test-input",
value: "03-12-1995",
defaultValue: "12-04-1995",
onChange: {
emit: onChange,
} as any,
onBlur: {
emit: onBlur,
} as any,
},
imports: [
MatDayjsDateModule,
MatNativeDateModule,
MatInputModule,
MatDatepickerModule,
MdePopoverModule,
DxcBoxModule,
CommonModule,
DxcTextInputModule,
],
providers: [
{ provide: MAT_DATE_FORMATS, useValue: DAYJS_DATE_FORMATS },
{
provide: DateAdapter,
useClass: DayjsDateAdapter,
deps: [MAT_DATE_LOCALE, Platform],
},
],
});
expect(screen.getByDisplayValue("03-12-1995"));
const input = <HTMLInputElement>screen.getByRole("textbox");
input.focus();
fireEvent.input(input, { target: { value: "03-10-1996" } });
expect(onChange).toHaveBeenCalledWith({
value: "03-10-1996",
error: undefined,
date: new Date("1996/10/03"),
});
expect(screen.getByDisplayValue("03-12-1995"));
fireEvent.blur(input);
waitFor(() => {
expect(onBlur).toHaveBeenCalledWith({
error: undefined,
value: "03-12-1995",
date: new Date("1995/12/03"),
});
});
});
});
Example #23
Source File: QueryBuilder_FetchStructure.test.tsx From legend-studio with Apache License 2.0 | 4 votes |
test(
integrationTest(
'Query builder state is properly set after processing a projection lambda',
),
async () => {
const pluginManager = LegendQueryPluginManager.create();
pluginManager.usePresets([new Query_GraphPreset()]).install();
const mockedQueryStore = TEST__provideMockedLegendQueryStore({
pluginManager,
});
const renderResult = await TEST__setUpQueryEditor(
mockedQueryStore,
TEST_DATA__ComplexRelationalModel,
stub_RawLambda(),
'model::relational::tests::simpleRelationalMapping',
'model::MyRuntime',
);
const queryBuilderState = mockedQueryStore.queryBuilderState;
const _personClass = mockedQueryStore.graphManagerState.graph.getClass(
'model::pure::tests::model::simple::Person',
);
const _firmClass = mockedQueryStore.graphManagerState.graph.getClass(
'model::pure::tests::model::simple::Firm',
);
const mapping = mockedQueryStore.graphManagerState.graph.getMapping(
'model::relational::tests::simpleRelationalMapping',
);
act(() => {
queryBuilderState.changeClass(_personClass);
});
const queryBuilderSetup = await waitFor(() =>
renderResult.getByTestId(QUERY_BUILDER_TEST_ID.QUERY_BUILDER_SETUP),
);
await waitFor(() => getByText(queryBuilderSetup, 'Person'));
await waitFor(() =>
getByText(queryBuilderSetup, 'simpleRelationalMapping'),
);
await waitFor(() => getByText(queryBuilderSetup, 'MyRuntime'));
const treeData = guaranteeNonNullable(
queryBuilderState.explorerState.treeData,
);
const rootNode = guaranteeType(
treeData.nodes.get(treeData.rootIds[0] as string),
QueryBuilderExplorerTreeRootNodeData,
);
expect(getRootSetImplementation(mapping, _personClass)).toBe(
rootNode.mappingData.targetSetImpl,
);
expect(rootNode.mappingData.mapped).toBe(true);
// simpleProjection
act(() => {
queryBuilderState.initialize(
create_RawLambda(
TEST_DATA__simpleProjection.parameters,
TEST_DATA__simpleProjection.body,
),
);
});
let projectionCols = await waitFor(() =>
renderResult.getByTestId(QUERY_BUILDER_TEST_ID.QUERY_BUILDER_PROJECTION),
);
const FIRST_NAME_ALIAS = 'Edited First Name';
const LAST_NAME_ALIAS = 'Last Name';
expect(
await waitFor(() =>
projectionCols.querySelector(`input[value="${FIRST_NAME_ALIAS}"]`),
),
).not.toBeNull();
expect(
await waitFor(() =>
projectionCols.querySelector(`input[value="${LAST_NAME_ALIAS}"]`),
),
).not.toBeNull();
expect(
queryBuilderState.fetchStructureState.projectionState.columns.length,
).toBe(2);
let fistNameCol = guaranteeNonNullable(
queryBuilderState.fetchStructureState.projectionState.columns.find(
(e) => e.columnName === FIRST_NAME_ALIAS,
),
);
const firstNameProperty = guaranteeType(
fistNameCol,
QueryBuilderSimpleProjectionColumnState,
).propertyExpressionState.propertyExpression.func;
expect(firstNameProperty).toBe(getClassProperty(_personClass, 'firstName'));
const lastNameCol = guaranteeNonNullable(
queryBuilderState.fetchStructureState.projectionState.columns.find(
(e) => e.columnName === LAST_NAME_ALIAS,
),
);
const lastNameProperty = guaranteeType(
lastNameCol,
QueryBuilderSimpleProjectionColumnState,
).propertyExpressionState.propertyExpression.func;
expect(lastNameProperty).toBe(getClassProperty(_personClass, 'lastName'));
expect(queryBuilderState.resultSetModifierState.limit).toBeUndefined();
// chainedProperty
const CHAINED_PROPERTY_ALIAS = 'Firm/Legal Name';
act(() => {
queryBuilderState.initialize(
create_RawLambda(
TEST_DATA__projectionWithChainedProperty.parameters,
TEST_DATA__projectionWithChainedProperty.body,
),
);
});
const projectionWithChainedPropertyCols = await waitFor(() =>
renderResult.getByTestId(QUERY_BUILDER_TEST_ID.QUERY_BUILDER_PROJECTION),
);
expect(
await waitFor(() =>
projectionWithChainedPropertyCols.querySelector(
`input[value="${CHAINED_PROPERTY_ALIAS}"]`,
),
),
).not.toBeNull();
expect(
queryBuilderState.fetchStructureState.projectionState.columns.length,
).toBe(1);
let legalNameCol = guaranteeNonNullable(
queryBuilderState.fetchStructureState.projectionState.columns.find(
(e) => e.columnName === CHAINED_PROPERTY_ALIAS,
),
);
const legalNameColProperty = guaranteeType(
legalNameCol,
QueryBuilderSimpleProjectionColumnState,
).propertyExpressionState.propertyExpression.func;
expect(legalNameColProperty).toBe(
getClassProperty(_firmClass, 'legalName'),
);
const _firmPropertyExpression = guaranteeType(
guaranteeType(legalNameCol, QueryBuilderSimpleProjectionColumnState)
.propertyExpressionState.propertyExpression.parametersValues[0],
AbstractPropertyExpression,
);
expect(_firmPropertyExpression.func).toBe(
getClassProperty(_personClass, 'firm'),
);
expect(queryBuilderState.resultSetModifierState.limit).toBeUndefined();
// result set modifiers
const RESULT_LIMIT = 500;
act(() => {
queryBuilderState.initialize(
create_RawLambda(
TEST_DATA__projectionWithResultSetModifiers.parameters,
TEST_DATA__projectionWithResultSetModifiers.body,
),
);
});
projectionCols = await waitFor(() =>
renderResult.getByTestId(QUERY_BUILDER_TEST_ID.QUERY_BUILDER_PROJECTION),
);
expect(
await waitFor(() =>
projectionCols.querySelector(`input[value="${FIRST_NAME_ALIAS}"]`),
),
).not.toBeNull();
expect(
await waitFor(() =>
projectionCols.querySelector(`input[value="${LAST_NAME_ALIAS}"]`),
),
).not.toBeNull();
expect(
await waitFor(() =>
projectionCols.querySelector(
`input[value="${CHAINED_PROPERTY_ALIAS}"]`,
),
),
).not.toBeNull();
expect(
queryBuilderState.fetchStructureState.projectionState.columns.length,
).toBe(3);
const resultSetModifierState = queryBuilderState.resultSetModifierState;
expect(resultSetModifierState.limit).toBe(RESULT_LIMIT);
expect(resultSetModifierState.distinct).toBe(true);
expect(resultSetModifierState.sortColumns).toHaveLength(2);
fistNameCol = guaranteeNonNullable(
queryBuilderState.fetchStructureState.projectionState.columns.find(
(e) => e.columnName === FIRST_NAME_ALIAS,
),
);
legalNameCol = guaranteeNonNullable(
queryBuilderState.fetchStructureState.projectionState.columns.find(
(e) => e.columnName === CHAINED_PROPERTY_ALIAS,
),
);
const firstnameSortState = guaranteeNonNullable(
resultSetModifierState.sortColumns.find(
(e) => e.columnState === fistNameCol,
),
);
expect(firstnameSortState.sortType).toBe(COLUMN_SORT_TYPE.ASC);
const legalNameColSortState = guaranteeNonNullable(
resultSetModifierState.sortColumns.find(
(e) => e.columnState === legalNameCol,
),
);
expect(legalNameColSortState.sortType).toBe(COLUMN_SORT_TYPE.DESC);
const queryBuilder = await waitFor(() =>
renderResult.getByTestId(QUERY_BUILDER_TEST_ID.QUERY_BUILDER),
);
fireEvent.click(
getByTitle(queryBuilder, 'Configure result set modifiers...'),
);
const modal = await waitFor(() => renderResult.getByRole('dialog'));
await waitFor(() => getByText(modal, 'Sort and Order'));
await waitFor(() => getByText(modal, 'Eliminate Duplicate Rows'));
await waitFor(() => getByText(modal, 'Limit Results'));
await waitFor(() => getByText(modal, FIRST_NAME_ALIAS));
await waitFor(() => getByText(modal, CHAINED_PROPERTY_ALIAS));
expect(
await waitFor(() =>
modal.querySelector(`input[value="${RESULT_LIMIT}"]`),
),
).not.toBeNull();
fireEvent.click(getByText(modal, 'Close'));
// filter with simple condition
await waitFor(() => renderResult.getByText('Add a filter condition'));
act(() => {
queryBuilderState.initialize(
create_RawLambda(
TEST_DATA__getAllWithOneConditionFilter.parameters,
TEST_DATA__getAllWithOneConditionFilter.body,
),
);
});
let filterValue = 'testFirstName';
let filterPanel = await waitFor(() =>
renderResult.getByTestId(QUERY_BUILDER_TEST_ID.QUERY_BUILDER_FILTER),
);
expect(
await waitFor(() =>
filterPanel.querySelector(`input[value="${filterValue}"]`),
),
).not.toBeNull();
await waitFor(() => getByText(filterPanel, 'First Name'));
await waitFor(() => getByText(filterPanel, 'is'));
const filterState = queryBuilderState.filterState;
expect(filterState.nodes.size).toBe(1);
expect(
queryBuilderState.fetchStructureState.projectionState.columns.length,
).toBe(0);
// filter with group condition
act(() => {
queryBuilderState.resetQueryBuilder();
queryBuilderState.resetQuerySetup();
});
await waitFor(() => renderResult.getByText('Add a filter condition'));
act(() => {
queryBuilderState.initialize(
create_RawLambda(
TEST_DATA__getAllWithGroupedFilter.parameters,
TEST_DATA__getAllWithGroupedFilter.body,
),
);
});
filterPanel = await waitFor(() =>
renderResult.getByTestId(QUERY_BUILDER_TEST_ID.QUERY_BUILDER_FILTER),
);
await waitFor(() =>
expect(getAllByText(filterPanel, 'is')).toHaveLength(2),
);
await waitFor(() => getByText(filterPanel, 'or'));
filterValue = 'lastNameTest';
expect(
await waitFor(() =>
filterPanel.querySelector(`input[value="${filterValue}"]`),
),
).not.toBeNull();
await waitFor(() => getByText(filterPanel, 'First Name'));
const lastNameFilterValue = 'lastNameTest';
expect(
await waitFor(() =>
filterPanel.querySelector(`input[value="${lastNameFilterValue}"]`),
),
).not.toBeNull();
await waitFor(() => getByText(filterPanel, 'Last Name'));
expect(queryBuilderState.filterState.nodes.size).toBe(3);
expect(
queryBuilderState.fetchStructureState.projectionState.columns.length,
).toBe(0);
// projection column with derived property
act(() => {
queryBuilderState.resetQueryBuilder();
queryBuilderState.resetQuerySetup();
});
await waitFor(() => renderResult.getByText('Add a filter condition'));
act(() => {
queryBuilderState.initialize(
create_RawLambda(
TEST_DATA__projectWithDerivedProperty.parameters,
TEST_DATA__projectWithDerivedProperty.body,
),
);
});
projectionCols = await waitFor(() =>
renderResult.getByTestId(QUERY_BUILDER_TEST_ID.QUERY_BUILDER_PROJECTION),
);
expect(
await waitFor(() =>
projectionCols.querySelector(`input[value="Full Name With Title"]`),
),
).not.toBeNull();
await waitFor(() => getByText(projectionCols, 'Name With Title'));
expect(
queryBuilderState.fetchStructureState.projectionState.columns.length,
).toBe(1);
fireEvent.click(
getByTitle(projectionCols, 'Set Derived Property Argument(s)...'),
);
const dpModal = await waitFor(() => renderResult.getByRole('dialog'));
await waitFor(() => getByText(dpModal, 'Derived Property'));
await waitFor(() => getByText(dpModal, 'Name With Title'));
await waitFor(() => getByText(dpModal, 'title'));
expect(
await waitFor(() => dpModal.querySelector(`input[value="Mr."]`)),
).not.toBeNull();
},
);