kopia lustrzana https://github.com/wagtail/wagtail
Update failing tests for Jest v29
- Use a console.error spy to avoid the console error bubbling into logs for FieldBlock.test.js (also allows us to confirm an error was thrown) - Adopt proper approach to 'flush promises' now that API is available for JSDom usage of microtasks/animation frame - Adapt to new Jest timer mocking approach, use legacy timers in one file as there is not a suitable setTimeout (with zero delay) while also using async awaitpull/10650/head
rodzic
f90e03ab35
commit
f80e64989e
|
@ -22,7 +22,7 @@ class DummyWidgetDefinition {
|
|||
|
||||
render(placeholder, name, id, initialState) {
|
||||
if (this.throwErrorOnRender) {
|
||||
throw new Error();
|
||||
throw new Error('Mock rendering error');
|
||||
}
|
||||
|
||||
const widgetName = this.widgetName;
|
||||
|
@ -190,6 +190,9 @@ describe('telepath: wagtail.blocks.FieldBlock catches widget render errors', ()
|
|||
let boundBlock;
|
||||
|
||||
beforeEach(() => {
|
||||
// mock console.error to ensure it does not bubble to the logs
|
||||
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
// Create mocks for callbacks
|
||||
constructor = jest.fn();
|
||||
setState = jest.fn();
|
||||
|
@ -212,6 +215,7 @@ describe('telepath: wagtail.blocks.FieldBlock catches widget render errors', ()
|
|||
|
||||
// Render it
|
||||
document.body.innerHTML = '<div id="placeholder"></div>';
|
||||
|
||||
boundBlock = blockDef.render(
|
||||
$('#placeholder'),
|
||||
'the-prefix',
|
||||
|
@ -219,7 +223,16 @@ describe('telepath: wagtail.blocks.FieldBlock catches widget render errors', ()
|
|||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
/* eslint-disable no-console */
|
||||
console.error.mockRestore();
|
||||
});
|
||||
|
||||
test('it renders correctly', () => {
|
||||
expect(console.error).toHaveBeenCalledTimes(1);
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
new Error('Mock rendering error'),
|
||||
);
|
||||
expect(document.body.innerHTML).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
import { Application } from '@hotwired/stimulus';
|
||||
import { ProgressController } from './ProgressController';
|
||||
|
||||
jest.useFakeTimers();
|
||||
|
||||
const flushPromises = () => new Promise(setImmediate);
|
||||
jest.useFakeTimers({ legacyFakeTimers: true });
|
||||
|
||||
describe('ProgressController', () => {
|
||||
// form submit is not implemented in jsdom
|
||||
|
@ -37,7 +35,7 @@ describe('ProgressController', () => {
|
|||
jest.clearAllTimers();
|
||||
});
|
||||
|
||||
it('should not change the text of the button to Loading if the form is not valid', async () => {
|
||||
it('should not change the text of the button to Loading if the form is not valid', () => {
|
||||
const form = document.querySelector('form');
|
||||
const button = document.querySelector('.button-longrunning');
|
||||
expect(mockSubmit).not.toHaveBeenCalled();
|
||||
|
@ -46,23 +44,15 @@ describe('ProgressController', () => {
|
|||
form.checkValidity = jest.fn().mockReturnValue(false);
|
||||
const onClick = jest.fn();
|
||||
button.addEventListener('click', onClick);
|
||||
|
||||
button.dispatchEvent(new CustomEvent('click'));
|
||||
|
||||
jest.advanceTimersByTime(10);
|
||||
await flushPromises();
|
||||
|
||||
expect(mockSubmit).not.toHaveBeenCalled();
|
||||
expect(setTimeout).not.toHaveBeenCalled();
|
||||
expect(button.disabled).toEqual(false);
|
||||
expect(onClick).toHaveBeenCalledTimes(1);
|
||||
|
||||
jest.runAllTimers();
|
||||
await flushPromises();
|
||||
|
||||
expect(mockSubmit).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should trigger a timeout based on the value attribute', () => {
|
||||
const form = document.querySelector('form');
|
||||
const button = document.querySelector('.button-longrunning');
|
||||
jest.spyOn(global, 'setTimeout');
|
||||
|
||||
|
@ -91,14 +81,14 @@ describe('ProgressController', () => {
|
|||
|
||||
button.click();
|
||||
jest.advanceTimersByTime(10);
|
||||
await flushPromises();
|
||||
await new Promise(queueMicrotask);
|
||||
|
||||
expect(label.textContent).toBe('Loading');
|
||||
expect(button.getAttribute('disabled')).toEqual('');
|
||||
expect(button.classList.contains('button-longrunning-active')).toBe(true);
|
||||
|
||||
jest.runAllTimers();
|
||||
await flushPromises();
|
||||
await new Promise(queueMicrotask);
|
||||
|
||||
expect(mockSubmit).toHaveBeenCalled();
|
||||
expect(label.textContent).toBe('Sign in');
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { setImmediate } from 'timers';
|
||||
import { Application } from '@hotwired/stimulus';
|
||||
import { SwapController } from './SwapController';
|
||||
import { range } from '../utils/range';
|
||||
|
|
|
@ -4,10 +4,15 @@ import { SyncController } from './SyncController';
|
|||
import { range } from '../utils/range';
|
||||
|
||||
jest.useFakeTimers();
|
||||
jest.spyOn(global, 'setTimeout');
|
||||
|
||||
describe('SyncController', () => {
|
||||
let application;
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('basic sync between two fields', () => {
|
||||
beforeEach(() => {
|
||||
application?.stop();
|
||||
|
|
|
@ -3,8 +3,6 @@ import $ from 'jquery';
|
|||
import { Application } from '@hotwired/stimulus';
|
||||
import { TagController } from './TagController';
|
||||
|
||||
const flushPromises = () => new Promise(setImmediate);
|
||||
|
||||
window.$ = $;
|
||||
|
||||
describe('TagController', () => {
|
||||
|
@ -41,7 +39,7 @@ describe('TagController', () => {
|
|||
someOther: 'option',
|
||||
});
|
||||
|
||||
await flushPromises();
|
||||
await new Promise(requestAnimationFrame);
|
||||
|
||||
// check the jQuery instance is the correct element
|
||||
expect(element).toContain(document.getElementById('tag-input'));
|
||||
|
@ -69,7 +67,7 @@ describe('TagController', () => {
|
|||
|
||||
window.initTagField('not-present');
|
||||
|
||||
await flushPromises();
|
||||
await new Promise(requestAnimationFrame);
|
||||
|
||||
expect(tagitMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
@ -90,7 +88,7 @@ describe('TagController', () => {
|
|||
|
||||
expect(tagitMock).not.toHaveBeenCalled();
|
||||
|
||||
await flushPromises();
|
||||
await new Promise(requestAnimationFrame);
|
||||
|
||||
expect(tagitMock).toHaveBeenCalledWith({
|
||||
allowSpaces: true,
|
||||
|
@ -116,7 +114,8 @@ describe('TagController', () => {
|
|||
.getElementById('id_tags')
|
||||
.dispatchEvent(new CustomEvent('example:event'));
|
||||
|
||||
await flushPromises();
|
||||
await new Promise(requestAnimationFrame);
|
||||
|
||||
expect(tagitMock).toHaveBeenCalledWith('removeAll');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,9 +2,6 @@ import { Application } from '@hotwired/stimulus';
|
|||
|
||||
import { UpgradeController } from './UpgradeController';
|
||||
|
||||
// https://stackoverflow.com/a/51045733
|
||||
const flushPromises = () => new Promise(setImmediate);
|
||||
|
||||
describe('UpgradeController', () => {
|
||||
let application;
|
||||
const url = 'https://releases.wagtail.org/mock.txt';
|
||||
|
@ -66,7 +63,7 @@ describe('UpgradeController', () => {
|
|||
document.getElementById('panel').classList.contains('w-hidden'),
|
||||
).toBe(true);
|
||||
|
||||
await flushPromises();
|
||||
await new Promise(requestAnimationFrame);
|
||||
|
||||
// should remove the hidden class on success
|
||||
expect(
|
||||
|
@ -112,7 +109,7 @@ describe('UpgradeController', () => {
|
|||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should throw an error if the fetch fails', () => {
|
||||
it('should throw an error if the fetch fails', async () => {
|
||||
// Spy on console.error to verify that it is called with the expected error message
|
||||
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
|
@ -127,17 +124,16 @@ describe('UpgradeController', () => {
|
|||
application.register('w-upgrade', UpgradeController);
|
||||
|
||||
// Wait for the catch block to be executed
|
||||
/* eslint-disable-next-line no-promise-executor-return */
|
||||
return new Promise((resolve) => setImmediate(resolve)).then(() => {
|
||||
// Verify that console.error was called with the expected error message
|
||||
/* eslint-disable-next-line no-console */
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
`Error fetching ${url}. Error: Error: Fetch failed`,
|
||||
);
|
||||
await new Promise(requestAnimationFrame);
|
||||
|
||||
// Restore the original implementation of console.error
|
||||
/* eslint-disable no-console */
|
||||
console.error.mockRestore();
|
||||
});
|
||||
// Verify that console.error was called with the expected error message
|
||||
/* eslint-disable-next-line no-console */
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
`Error fetching ${url}. Error: Error: Fetch failed`,
|
||||
);
|
||||
|
||||
// Restore the original implementation of console.error
|
||||
/* eslint-disable no-console */
|
||||
console.error.mockRestore();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import { initIconSprite } from './initIconSprite';
|
||||
|
||||
const flushPromises = () => new Promise(setImmediate);
|
||||
|
||||
describe('initIconSprite', () => {
|
||||
const spriteURL = 'https://example.com/sprite.svg';
|
||||
const responseText = '<svg>...</svg>';
|
||||
|
@ -22,7 +20,7 @@ describe('initIconSprite', () => {
|
|||
text: () => Promise.resolve(responseText),
|
||||
});
|
||||
initIconSprite(spriteContainer, spriteURL);
|
||||
await flushPromises();
|
||||
await new Promise(requestAnimationFrame);
|
||||
|
||||
expect(global.fetch).toHaveBeenCalled();
|
||||
expect(global.fetch).toHaveBeenCalledWith(spriteURL);
|
||||
|
@ -38,7 +36,7 @@ describe('initIconSprite', () => {
|
|||
text: () => Promise.resolve(responseText),
|
||||
});
|
||||
initIconSprite(spriteContainer, spriteURL);
|
||||
await flushPromises();
|
||||
await new Promise(requestAnimationFrame);
|
||||
|
||||
expect(localStorage).not.toBe(null);
|
||||
expect(localStorage['wagtail:spriteData']).toBe(responseText);
|
||||
|
@ -51,7 +49,7 @@ describe('initIconSprite', () => {
|
|||
const spy = jest.spyOn(console, 'error').mockImplementation();
|
||||
|
||||
initIconSprite(spriteContainer, spriteURL);
|
||||
await flushPromises();
|
||||
await new Promise(requestAnimationFrame);
|
||||
|
||||
expect(global.fetch).toHaveBeenCalled();
|
||||
expect(global.fetch).toHaveBeenCalledWith(spriteURL);
|
||||
|
|
Ładowanie…
Reference in New Issue