Index: frontend/node_modules/eslint-plugin-testing-library/rules/await-async-query.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/await-async-query.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/await-async-query.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,83 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'await-async-query';
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'problem',
+        docs: {
+            description: 'Enforce promises from async queries to be handled',
+            recommendedConfig: {
+                dom: 'error',
+                angular: 'error',
+                react: 'error',
+                vue: 'error',
+                marko: 'error',
+            },
+        },
+        messages: {
+            awaitAsyncQuery: 'promise returned from `{{ name }}` query must be handled',
+            asyncQueryWrapper: 'promise returned from `{{ name }}` wrapper over async query must be handled',
+        },
+        schema: [],
+    },
+    defaultOptions: [],
+    create(context, _, helpers) {
+        const functionWrappersNames = [];
+        function detectAsyncQueryWrapper(node) {
+            const innerFunction = (0, node_utils_1.getInnermostReturningFunction)(context, node);
+            if (innerFunction) {
+                functionWrappersNames.push((0, node_utils_1.getFunctionName)(innerFunction));
+            }
+        }
+        return {
+            CallExpression(node) {
+                const identifierNode = (0, node_utils_1.getDeepestIdentifierNode)(node);
+                if (!identifierNode) {
+                    return;
+                }
+                if (helpers.isAsyncQuery(identifierNode)) {
+                    detectAsyncQueryWrapper(identifierNode);
+                    const closestCallExpressionNode = (0, node_utils_1.findClosestCallExpressionNode)(node, true);
+                    if (!(closestCallExpressionNode === null || closestCallExpressionNode === void 0 ? void 0 : closestCallExpressionNode.parent)) {
+                        return;
+                    }
+                    const references = (0, node_utils_1.getVariableReferences)(context, closestCallExpressionNode.parent);
+                    if (references.length === 0) {
+                        if (!(0, node_utils_1.isPromiseHandled)(identifierNode)) {
+                            context.report({
+                                node: identifierNode,
+                                messageId: 'awaitAsyncQuery',
+                                data: { name: identifierNode.name },
+                            });
+                            return;
+                        }
+                    }
+                    for (const reference of references) {
+                        if (utils_1.ASTUtils.isIdentifier(reference.identifier) &&
+                            !(0, node_utils_1.isPromiseHandled)(reference.identifier)) {
+                            context.report({
+                                node: identifierNode,
+                                messageId: 'awaitAsyncQuery',
+                                data: { name: identifierNode.name },
+                            });
+                            return;
+                        }
+                    }
+                }
+                else if (functionWrappersNames.includes(identifierNode.name) &&
+                    !(0, node_utils_1.isPromiseHandled)(identifierNode)) {
+                    context.report({
+                        node: identifierNode,
+                        messageId: 'asyncQueryWrapper',
+                        data: { name: identifierNode.name },
+                    });
+                }
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/await-async-utils.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/await-async-utils.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/await-async-utils.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,122 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'await-async-utils';
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'problem',
+        docs: {
+            description: 'Enforce promises from async utils to be awaited properly',
+            recommendedConfig: {
+                dom: 'error',
+                angular: 'error',
+                react: 'error',
+                vue: 'error',
+                marko: 'error',
+            },
+        },
+        messages: {
+            awaitAsyncUtil: 'Promise returned from `{{ name }}` must be handled',
+            asyncUtilWrapper: 'Promise returned from {{ name }} wrapper over async util must be handled',
+        },
+        schema: [],
+    },
+    defaultOptions: [],
+    create(context, _, helpers) {
+        const functionWrappersNames = [];
+        function detectAsyncUtilWrapper(node) {
+            const innerFunction = (0, node_utils_1.getInnermostReturningFunction)(context, node);
+            if (!innerFunction) {
+                return;
+            }
+            const functionName = (0, node_utils_1.getFunctionName)(innerFunction);
+            if (functionName.length === 0) {
+                return;
+            }
+            functionWrappersNames.push(functionName);
+        }
+        function detectDestructuredAsyncUtilWrapperAliases(node) {
+            for (const property of node.properties) {
+                if (!(0, node_utils_1.isProperty)(property)) {
+                    continue;
+                }
+                if (!utils_1.ASTUtils.isIdentifier(property.key) ||
+                    !utils_1.ASTUtils.isIdentifier(property.value)) {
+                    continue;
+                }
+                if (functionWrappersNames.includes(property.key.name)) {
+                    const isDestructuredAsyncWrapperPropertyRenamed = property.key.name !== property.value.name;
+                    if (isDestructuredAsyncWrapperPropertyRenamed) {
+                        functionWrappersNames.push(property.value.name);
+                    }
+                }
+            }
+        }
+        const getMessageId = (node) => {
+            if (helpers.isAsyncUtil(node)) {
+                return 'awaitAsyncUtil';
+            }
+            return 'asyncUtilWrapper';
+        };
+        return {
+            VariableDeclarator(node) {
+                var _a, _b;
+                if ((0, node_utils_1.isObjectPattern)(node.id)) {
+                    detectDestructuredAsyncUtilWrapperAliases(node.id);
+                    return;
+                }
+                const isAssigningKnownAsyncFunctionWrapper = utils_1.ASTUtils.isIdentifier(node.id) &&
+                    node.init !== null &&
+                    functionWrappersNames.includes((_b = (_a = (0, node_utils_1.getDeepestIdentifierNode)(node.init)) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : '');
+                if (isAssigningKnownAsyncFunctionWrapper) {
+                    functionWrappersNames.push(node.id.name);
+                }
+            },
+            'CallExpression Identifier'(node) {
+                const isAsyncUtilOrKnownAliasAroundIt = helpers.isAsyncUtil(node) ||
+                    functionWrappersNames.includes(node.name);
+                if (!isAsyncUtilOrKnownAliasAroundIt) {
+                    return;
+                }
+                if (helpers.isAsyncUtil(node)) {
+                    detectAsyncUtilWrapper(node);
+                }
+                const closestCallExpression = (0, node_utils_1.findClosestCallExpressionNode)(node, true);
+                if (!(closestCallExpression === null || closestCallExpression === void 0 ? void 0 : closestCallExpression.parent)) {
+                    return;
+                }
+                const references = (0, node_utils_1.getVariableReferences)(context, closestCallExpression.parent);
+                if (references.length === 0) {
+                    if (!(0, node_utils_1.isPromiseHandled)(node)) {
+                        context.report({
+                            node,
+                            messageId: getMessageId(node),
+                            data: {
+                                name: node.name,
+                            },
+                        });
+                    }
+                }
+                else {
+                    for (const reference of references) {
+                        const referenceNode = reference.identifier;
+                        if (!(0, node_utils_1.isPromiseHandled)(referenceNode)) {
+                            context.report({
+                                node,
+                                messageId: getMessageId(node),
+                                data: {
+                                    name: node.name,
+                                },
+                            });
+                            return;
+                        }
+                    }
+                }
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/await-fire-event.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/await-fire-event.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/await-fire-event.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,76 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'await-fire-event';
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'problem',
+        docs: {
+            description: 'Enforce promises from `fireEvent` methods to be handled',
+            recommendedConfig: {
+                dom: false,
+                angular: false,
+                react: false,
+                vue: 'error',
+                marko: 'error',
+            },
+        },
+        messages: {
+            awaitFireEvent: 'Promise returned from `fireEvent.{{ name }}` must be handled',
+            fireEventWrapper: 'Promise returned from `{{ name }}` wrapper over fire event method must be handled',
+        },
+        schema: [],
+    },
+    defaultOptions: [],
+    create(context, _, helpers) {
+        const functionWrappersNames = [];
+        function reportUnhandledNode(node, closestCallExpressionNode, messageId = 'awaitFireEvent') {
+            if (!(0, node_utils_1.isPromiseHandled)(node)) {
+                context.report({
+                    node: closestCallExpressionNode.callee,
+                    messageId,
+                    data: { name: node.name },
+                });
+            }
+        }
+        function detectFireEventMethodWrapper(node) {
+            const innerFunction = (0, node_utils_1.getInnermostReturningFunction)(context, node);
+            if (innerFunction) {
+                functionWrappersNames.push((0, node_utils_1.getFunctionName)(innerFunction));
+            }
+        }
+        return {
+            'CallExpression Identifier'(node) {
+                if (helpers.isFireEventMethod(node)) {
+                    detectFireEventMethodWrapper(node);
+                    const closestCallExpression = (0, node_utils_1.findClosestCallExpressionNode)(node, true);
+                    if (!(closestCallExpression === null || closestCallExpression === void 0 ? void 0 : closestCallExpression.parent)) {
+                        return;
+                    }
+                    const references = (0, node_utils_1.getVariableReferences)(context, closestCallExpression.parent);
+                    if (references.length === 0) {
+                        reportUnhandledNode(node, closestCallExpression);
+                    }
+                    else {
+                        for (const reference of references) {
+                            if (utils_1.ASTUtils.isIdentifier(reference.identifier)) {
+                                reportUnhandledNode(reference.identifier, closestCallExpression);
+                            }
+                        }
+                    }
+                }
+                else if (functionWrappersNames.includes(node.name)) {
+                    const closestCallExpression = (0, node_utils_1.findClosestCallExpressionNode)(node, true);
+                    if (!closestCallExpression) {
+                        return;
+                    }
+                    reportUnhandledNode(node, closestCallExpression, 'fireEventWrapper');
+                }
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/consistent-data-testid.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/consistent-data-testid.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/consistent-data-testid.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,129 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'consistent-data-testid';
+const FILENAME_PLACEHOLDER = '{fileName}';
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'suggestion',
+        docs: {
+            description: 'Ensures consistent usage of `data-testid`',
+            recommendedConfig: {
+                dom: false,
+                angular: false,
+                react: false,
+                vue: false,
+                marko: false,
+            },
+        },
+        messages: {
+            consistentDataTestId: '`{{attr}}` "{{value}}" should match `{{regex}}`',
+            consistentDataTestIdCustomMessage: '`{{message}}`',
+        },
+        schema: [
+            {
+                type: 'object',
+                default: {},
+                additionalProperties: false,
+                required: ['testIdPattern'],
+                properties: {
+                    testIdPattern: {
+                        type: 'string',
+                    },
+                    testIdAttribute: {
+                        default: 'data-testid',
+                        oneOf: [
+                            {
+                                type: 'string',
+                            },
+                            {
+                                type: 'array',
+                                items: {
+                                    type: 'string',
+                                },
+                            },
+                        ],
+                    },
+                    customMessage: {
+                        default: undefined,
+                        type: 'string',
+                    },
+                },
+            },
+        ],
+    },
+    defaultOptions: [
+        {
+            testIdPattern: '',
+            testIdAttribute: 'data-testid',
+            customMessage: undefined,
+        },
+    ],
+    detectionOptions: {
+        skipRuleReportingCheck: true,
+    },
+    create: (context, [options]) => {
+        const { getFilename } = context;
+        const { testIdPattern, testIdAttribute: attr, customMessage } = options;
+        function getFileNameData() {
+            var _a;
+            const splitPath = getFilename().split('/');
+            const fileNameWithExtension = (_a = splitPath.pop()) !== null && _a !== void 0 ? _a : '';
+            if (fileNameWithExtension.includes('[') ||
+                fileNameWithExtension.includes(']')) {
+                return { fileName: undefined };
+            }
+            const parent = splitPath.pop();
+            const fileName = fileNameWithExtension.split('.').shift();
+            return {
+                fileName: fileName === 'index' ? parent : fileName,
+            };
+        }
+        function getTestIdValidator(fileName) {
+            return new RegExp(testIdPattern.replace(FILENAME_PLACEHOLDER, fileName));
+        }
+        function isTestIdAttribute(name) {
+            var _a;
+            if (typeof attr === 'string') {
+                return attr === name;
+            }
+            else {
+                return (_a = attr === null || attr === void 0 ? void 0 : attr.includes(name)) !== null && _a !== void 0 ? _a : false;
+            }
+        }
+        function getErrorMessageId() {
+            if (customMessage === undefined) {
+                return 'consistentDataTestId';
+            }
+            return 'consistentDataTestIdCustomMessage';
+        }
+        return {
+            JSXIdentifier: (node) => {
+                if (!node.parent ||
+                    !(0, node_utils_1.isJSXAttribute)(node.parent) ||
+                    !(0, node_utils_1.isLiteral)(node.parent.value) ||
+                    !isTestIdAttribute(node.name)) {
+                    return;
+                }
+                const value = node.parent.value.value;
+                const { fileName } = getFileNameData();
+                const regex = getTestIdValidator(fileName !== null && fileName !== void 0 ? fileName : '');
+                if (value && typeof value === 'string' && !regex.test(value)) {
+                    context.report({
+                        node,
+                        messageId: getErrorMessageId(),
+                        data: {
+                            attr: node.name,
+                            value,
+                            regex,
+                            message: customMessage,
+                        },
+                    });
+                }
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/index.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/index.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/index.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,11 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const fs_1 = require("fs");
+const path_1 = require("path");
+const utils_1 = require("../utils");
+const rulesDir = __dirname;
+const excludedFiles = ['index'];
+exports.default = (0, fs_1.readdirSync)(rulesDir)
+    .map((rule) => (0, path_1.parse)(rule).name)
+    .filter((ruleName) => !excludedFiles.includes(ruleName))
+    .reduce((allRules, ruleName) => (Object.assign(Object.assign({}, allRules), { [ruleName]: (0, utils_1.importDefault)((0, path_1.join)(rulesDir, ruleName)) })), {});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/no-await-sync-events.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/no-await-sync-events.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/no-await-sync-events.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,113 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+const USER_EVENT_ASYNC_EXCEPTIONS = ['type', 'keyboard'];
+const VALID_EVENT_MODULES = ['fire-event', 'user-event'];
+exports.RULE_NAME = 'no-await-sync-events';
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'problem',
+        docs: {
+            description: 'Disallow unnecessary `await` for sync events',
+            recommendedConfig: {
+                dom: false,
+                angular: false,
+                react: false,
+                vue: false,
+                marko: false,
+            },
+        },
+        messages: {
+            noAwaitSyncEvents: '`{{ name }}` is sync and does not need `await` operator',
+        },
+        schema: [
+            {
+                type: 'object',
+                properties: {
+                    eventModules: {
+                        type: 'array',
+                        minItems: 1,
+                        items: {
+                            enum: VALID_EVENT_MODULES,
+                        },
+                    },
+                },
+                additionalProperties: false,
+            },
+        ],
+    },
+    defaultOptions: [{ eventModules: VALID_EVENT_MODULES }],
+    create(context, [options], helpers) {
+        const { eventModules = VALID_EVENT_MODULES } = options;
+        let hasDelayDeclarationOrAssignmentGTZero;
+        return {
+            VariableDeclaration(node) {
+                hasDelayDeclarationOrAssignmentGTZero = node.declarations.some((property) => utils_1.ASTUtils.isIdentifier(property.id) &&
+                    property.id.name === 'delay' &&
+                    (0, node_utils_1.isLiteral)(property.init) &&
+                    property.init.value &&
+                    property.init.value > 0);
+            },
+            AssignmentExpression(node) {
+                if (utils_1.ASTUtils.isIdentifier(node.left) &&
+                    node.left.name === 'delay' &&
+                    (0, node_utils_1.isLiteral)(node.right) &&
+                    node.right.value !== null) {
+                    hasDelayDeclarationOrAssignmentGTZero = node.right.value > 0;
+                }
+            },
+            'AwaitExpression > CallExpression'(node) {
+                var _a;
+                const simulateEventFunctionIdentifier = (0, node_utils_1.getDeepestIdentifierNode)(node);
+                if (!simulateEventFunctionIdentifier) {
+                    return;
+                }
+                const isUserEventMethod = helpers.isUserEventMethod(simulateEventFunctionIdentifier);
+                const isFireEventMethod = helpers.isFireEventMethod(simulateEventFunctionIdentifier);
+                const isSimulateEventMethod = isUserEventMethod || isFireEventMethod;
+                if (!isSimulateEventMethod) {
+                    return;
+                }
+                if (isFireEventMethod && !eventModules.includes('fire-event')) {
+                    return;
+                }
+                if (isUserEventMethod && !eventModules.includes('user-event')) {
+                    return;
+                }
+                const lastArg = node.arguments[node.arguments.length - 1];
+                const hasDelayProperty = (0, node_utils_1.isObjectExpression)(lastArg) &&
+                    lastArg.properties.some((property) => (0, node_utils_1.isProperty)(property) &&
+                        utils_1.ASTUtils.isIdentifier(property.key) &&
+                        property.key.name === 'delay');
+                const hasDelayLiteralGTZero = (0, node_utils_1.isObjectExpression)(lastArg) &&
+                    lastArg.properties.some((property) => (0, node_utils_1.isProperty)(property) &&
+                        utils_1.ASTUtils.isIdentifier(property.key) &&
+                        property.key.name === 'delay' &&
+                        (0, node_utils_1.isLiteral)(property.value) &&
+                        !!property.value.value &&
+                        property.value.value > 0);
+                const simulateEventFunctionName = simulateEventFunctionIdentifier.name;
+                if (USER_EVENT_ASYNC_EXCEPTIONS.includes(simulateEventFunctionName) &&
+                    hasDelayProperty &&
+                    (hasDelayDeclarationOrAssignmentGTZero || hasDelayLiteralGTZero)) {
+                    return;
+                }
+                const eventModuleName = (_a = (0, node_utils_1.getPropertyIdentifierNode)(node)) === null || _a === void 0 ? void 0 : _a.name;
+                const eventFullName = eventModuleName
+                    ? `${eventModuleName}.${simulateEventFunctionName}`
+                    : simulateEventFunctionName;
+                context.report({
+                    node,
+                    messageId: 'noAwaitSyncEvents',
+                    data: {
+                        name: eventFullName,
+                    },
+                });
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/no-await-sync-query.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/no-await-sync-query.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/no-await-sync-query.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,46 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'no-await-sync-query';
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'problem',
+        docs: {
+            description: 'Disallow unnecessary `await` for sync queries',
+            recommendedConfig: {
+                dom: 'error',
+                angular: 'error',
+                react: 'error',
+                vue: 'error',
+                marko: 'error',
+            },
+        },
+        messages: {
+            noAwaitSyncQuery: '`{{ name }}` query is sync so it does not need to be awaited',
+        },
+        schema: [],
+    },
+    defaultOptions: [],
+    create(context, _, helpers) {
+        return {
+            'AwaitExpression > CallExpression'(node) {
+                const deepestIdentifierNode = (0, node_utils_1.getDeepestIdentifierNode)(node);
+                if (!deepestIdentifierNode) {
+                    return;
+                }
+                if (helpers.isSyncQuery(deepestIdentifierNode)) {
+                    context.report({
+                        node: deepestIdentifierNode,
+                        messageId: 'noAwaitSyncQuery',
+                        data: {
+                            name: deepestIdentifierNode.name,
+                        },
+                    });
+                }
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/no-container.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/no-container.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/no-container.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,123 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'no-container';
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'problem',
+        docs: {
+            description: 'Disallow the use of `container` methods',
+            recommendedConfig: {
+                dom: false,
+                angular: 'error',
+                react: 'error',
+                vue: 'error',
+                marko: 'error',
+            },
+        },
+        messages: {
+            noContainer: 'Avoid using container methods. Prefer using the methods from Testing Library, such as "getByRole()"',
+        },
+        schema: [],
+    },
+    defaultOptions: [],
+    create(context, _, helpers) {
+        const destructuredContainerPropNames = [];
+        const renderWrapperNames = [];
+        let renderResultVarName = null;
+        let containerName = null;
+        let containerCallsMethod = false;
+        function detectRenderWrapper(node) {
+            const innerFunction = (0, node_utils_1.getInnermostReturningFunction)(context, node);
+            if (innerFunction) {
+                renderWrapperNames.push((0, node_utils_1.getFunctionName)(innerFunction));
+            }
+        }
+        function showErrorIfChainedContainerMethod(innerNode) {
+            if ((0, node_utils_1.isMemberExpression)(innerNode)) {
+                if (utils_1.ASTUtils.isIdentifier(innerNode.object)) {
+                    const isContainerName = innerNode.object.name === containerName;
+                    if (isContainerName) {
+                        context.report({
+                            node: innerNode,
+                            messageId: 'noContainer',
+                        });
+                        return;
+                    }
+                    const isRenderWrapper = innerNode.object.name === renderResultVarName;
+                    containerCallsMethod =
+                        utils_1.ASTUtils.isIdentifier(innerNode.property) &&
+                            innerNode.property.name === 'container' &&
+                            isRenderWrapper;
+                    if (containerCallsMethod) {
+                        context.report({
+                            node: innerNode.property,
+                            messageId: 'noContainer',
+                        });
+                        return;
+                    }
+                }
+                showErrorIfChainedContainerMethod(innerNode.object);
+            }
+        }
+        return {
+            CallExpression(node) {
+                const callExpressionIdentifier = (0, node_utils_1.getDeepestIdentifierNode)(node);
+                if (!callExpressionIdentifier) {
+                    return;
+                }
+                if (helpers.isRenderUtil(callExpressionIdentifier)) {
+                    detectRenderWrapper(callExpressionIdentifier);
+                }
+                if ((0, node_utils_1.isMemberExpression)(node.callee)) {
+                    showErrorIfChainedContainerMethod(node.callee);
+                }
+                else if (utils_1.ASTUtils.isIdentifier(node.callee) &&
+                    destructuredContainerPropNames.includes(node.callee.name)) {
+                    context.report({
+                        node,
+                        messageId: 'noContainer',
+                    });
+                }
+            },
+            VariableDeclarator(node) {
+                if (!node.init) {
+                    return;
+                }
+                const initIdentifierNode = (0, node_utils_1.getDeepestIdentifierNode)(node.init);
+                if (!initIdentifierNode) {
+                    return;
+                }
+                const isRenderWrapperVariableDeclarator = renderWrapperNames.includes(initIdentifierNode.name);
+                if (!helpers.isRenderVariableDeclarator(node) &&
+                    !isRenderWrapperVariableDeclarator) {
+                    return;
+                }
+                if ((0, node_utils_1.isObjectPattern)(node.id)) {
+                    const containerIndex = node.id.properties.findIndex((property) => (0, node_utils_1.isProperty)(property) &&
+                        utils_1.ASTUtils.isIdentifier(property.key) &&
+                        property.key.name === 'container');
+                    const nodeValue = containerIndex !== -1 && node.id.properties[containerIndex].value;
+                    if (!nodeValue) {
+                        return;
+                    }
+                    if (utils_1.ASTUtils.isIdentifier(nodeValue)) {
+                        containerName = nodeValue.name;
+                    }
+                    else if ((0, node_utils_1.isObjectPattern)(nodeValue)) {
+                        nodeValue.properties.forEach((property) => (0, node_utils_1.isProperty)(property) &&
+                            utils_1.ASTUtils.isIdentifier(property.key) &&
+                            destructuredContainerPropNames.push(property.key.name));
+                    }
+                }
+                else if (utils_1.ASTUtils.isIdentifier(node.id)) {
+                    renderResultVarName = node.id.name;
+                }
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/no-debugging-utils.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/no-debugging-utils.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/no-debugging-utils.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,125 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+const utils_2 = require("../utils");
+exports.RULE_NAME = 'no-debugging-utils';
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'problem',
+        docs: {
+            description: 'Disallow the use of debugging utilities like `debug`',
+            recommendedConfig: {
+                dom: false,
+                angular: 'error',
+                react: 'error',
+                vue: 'error',
+                marko: 'error',
+            },
+        },
+        messages: {
+            noDebug: 'Unexpected debug statement',
+        },
+        schema: [
+            {
+                type: 'object',
+                properties: {
+                    utilsToCheckFor: {
+                        type: 'object',
+                        properties: utils_2.DEBUG_UTILS.reduce((obj, name) => (Object.assign({ [name]: { type: 'boolean' } }, obj)), {}),
+                        additionalProperties: false,
+                    },
+                },
+                additionalProperties: false,
+            },
+        ],
+    },
+    defaultOptions: [
+        { utilsToCheckFor: { debug: true, logTestingPlaygroundURL: true } },
+    ],
+    create(context, [{ utilsToCheckFor = {} }], helpers) {
+        const suspiciousDebugVariableNames = [];
+        const suspiciousReferenceNodes = [];
+        const renderWrapperNames = [];
+        const builtInConsoleNodes = [];
+        const utilsToReport = Object.entries(utilsToCheckFor)
+            .filter(([, shouldCheckFor]) => shouldCheckFor)
+            .map(([name]) => name);
+        function detectRenderWrapper(node) {
+            const innerFunction = (0, node_utils_1.getInnermostReturningFunction)(context, node);
+            if (innerFunction) {
+                renderWrapperNames.push((0, node_utils_1.getFunctionName)(innerFunction));
+            }
+        }
+        return {
+            VariableDeclarator(node) {
+                if (!node.init) {
+                    return;
+                }
+                const initIdentifierNode = (0, node_utils_1.getDeepestIdentifierNode)(node.init);
+                if (!initIdentifierNode) {
+                    return;
+                }
+                if (initIdentifierNode.name === 'console') {
+                    builtInConsoleNodes.push(node);
+                    return;
+                }
+                const isRenderWrapperVariableDeclarator = renderWrapperNames.includes(initIdentifierNode.name);
+                if (!helpers.isRenderVariableDeclarator(node) &&
+                    !isRenderWrapperVariableDeclarator) {
+                    return;
+                }
+                if ((0, node_utils_1.isObjectPattern)(node.id)) {
+                    for (const property of node.id.properties) {
+                        if ((0, node_utils_1.isProperty)(property) &&
+                            utils_1.ASTUtils.isIdentifier(property.key) &&
+                            utilsToReport.includes(property.key.name)) {
+                            const identifierNode = (0, node_utils_1.getDeepestIdentifierNode)(property.value);
+                            if (identifierNode) {
+                                suspiciousDebugVariableNames.push(identifierNode.name);
+                            }
+                        }
+                    }
+                }
+                if (utils_1.ASTUtils.isIdentifier(node.id)) {
+                    suspiciousReferenceNodes.push(node.id);
+                }
+            },
+            CallExpression(node) {
+                const callExpressionIdentifier = (0, node_utils_1.getDeepestIdentifierNode)(node);
+                if (!callExpressionIdentifier) {
+                    return;
+                }
+                if (helpers.isRenderUtil(callExpressionIdentifier)) {
+                    detectRenderWrapper(callExpressionIdentifier);
+                }
+                const referenceNode = (0, node_utils_1.getReferenceNode)(node);
+                const referenceIdentifier = (0, node_utils_1.getPropertyIdentifierNode)(referenceNode);
+                if (!referenceIdentifier) {
+                    return;
+                }
+                const isDebugUtil = helpers.isDebugUtil(callExpressionIdentifier, utilsToReport);
+                const isDeclaredDebugVariable = suspiciousDebugVariableNames.includes(callExpressionIdentifier.name);
+                const isChainedReferenceDebug = suspiciousReferenceNodes.some((suspiciousReferenceIdentifier) => {
+                    return (utilsToReport.includes(callExpressionIdentifier.name) &&
+                        suspiciousReferenceIdentifier.name === referenceIdentifier.name);
+                });
+                const isVariableFromBuiltInConsole = builtInConsoleNodes.some((variableDeclarator) => {
+                    const variables = context.getDeclaredVariables(variableDeclarator);
+                    return variables.some(({ name }) => name === callExpressionIdentifier.name &&
+                        (0, node_utils_1.isCallExpression)(callExpressionIdentifier.parent));
+                });
+                if (!isVariableFromBuiltInConsole &&
+                    (isDebugUtil || isDeclaredDebugVariable || isChainedReferenceDebug)) {
+                    context.report({
+                        node: callExpressionIdentifier,
+                        messageId: 'noDebug',
+                    });
+                }
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/no-dom-import.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/no-dom-import.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/no-dom-import.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,81 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'no-dom-import';
+const DOM_TESTING_LIBRARY_MODULES = [
+    'dom-testing-library',
+    '@testing-library/dom',
+];
+const CORRECT_MODULE_NAME_BY_FRAMEWORK = {
+    angular: '@testing-library/angular',
+    marko: '@marko/testing-library',
+};
+const getCorrectModuleName = (moduleName, framework) => {
+    var _a;
+    return ((_a = CORRECT_MODULE_NAME_BY_FRAMEWORK[framework]) !== null && _a !== void 0 ? _a : moduleName.replace('dom', framework));
+};
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'problem',
+        docs: {
+            description: 'Disallow importing from DOM Testing Library',
+            recommendedConfig: {
+                dom: false,
+                angular: ['error', 'angular'],
+                react: ['error', 'react'],
+                vue: ['error', 'vue'],
+                marko: ['error', 'marko'],
+            },
+        },
+        messages: {
+            noDomImport: 'import from DOM Testing Library is restricted, import from corresponding Testing Library framework instead',
+            noDomImportFramework: 'import from DOM Testing Library is restricted, import from {{module}} instead',
+        },
+        fixable: 'code',
+        schema: [{ type: 'string' }],
+    },
+    defaultOptions: [''],
+    create(context, [framework], helpers) {
+        function report(node, moduleName) {
+            if (!framework) {
+                return context.report({
+                    node,
+                    messageId: 'noDomImport',
+                });
+            }
+            const correctModuleName = getCorrectModuleName(moduleName, framework);
+            context.report({
+                data: { module: correctModuleName },
+                fix(fixer) {
+                    if ((0, node_utils_1.isCallExpression)(node)) {
+                        const name = node.arguments[0];
+                        return fixer.replaceText(name, name.raw.replace(moduleName, correctModuleName));
+                    }
+                    else {
+                        const name = node.source;
+                        return fixer.replaceText(name, name.raw.replace(moduleName, correctModuleName));
+                    }
+                },
+                messageId: 'noDomImportFramework',
+                node,
+            });
+        }
+        return {
+            'Program:exit'() {
+                let importName;
+                const allImportNodes = helpers.getAllTestingLibraryImportNodes();
+                allImportNodes.forEach((importNode) => {
+                    importName = (0, node_utils_1.getImportModuleName)(importNode);
+                    const domModuleName = DOM_TESTING_LIBRARY_MODULES.find((module) => module === importName);
+                    if (!domModuleName) {
+                        return;
+                    }
+                    report(importNode, domModuleName);
+                });
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/no-global-regexp-flag-in-query.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/no-global-regexp-flag-in-query.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/no-global-regexp-flag-in-query.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,122 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'no-global-regexp-flag-in-query';
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'suggestion',
+        docs: {
+            description: 'Disallow the use of the global RegExp flag (/g) in queries',
+            recommendedConfig: {
+                dom: false,
+                angular: false,
+                react: false,
+                vue: false,
+                marko: false,
+            },
+        },
+        messages: {
+            noGlobalRegExpFlagInQuery: 'Avoid using the global RegExp flag (/g) in queries',
+        },
+        fixable: 'code',
+        schema: [],
+    },
+    defaultOptions: [],
+    create(context, _, helpers) {
+        function reportLiteralWithRegex(literalNode) {
+            if ((0, node_utils_1.isLiteral)(literalNode) &&
+                'regex' in literalNode &&
+                literalNode.regex.flags.includes('g')) {
+                context.report({
+                    node: literalNode,
+                    messageId: 'noGlobalRegExpFlagInQuery',
+                    fix(fixer) {
+                        const splitter = literalNode.raw.lastIndexOf('/');
+                        const raw = literalNode.raw.substring(0, splitter);
+                        const flags = literalNode.raw.substring(splitter + 1);
+                        const flagsWithoutGlobal = flags.replace('g', '');
+                        return fixer.replaceText(literalNode, `${raw}/${flagsWithoutGlobal}`);
+                    },
+                });
+                return true;
+            }
+            return false;
+        }
+        function getArguments(identifierNode) {
+            if ((0, node_utils_1.isCallExpression)(identifierNode.parent)) {
+                return identifierNode.parent.arguments;
+            }
+            else if ((0, node_utils_1.isMemberExpression)(identifierNode.parent) &&
+                (0, node_utils_1.isCallExpression)(identifierNode.parent.parent)) {
+                return identifierNode.parent.parent.arguments;
+            }
+            return [];
+        }
+        const variableNodesWithRegexs = [];
+        function hasRegexInVariable(identifier) {
+            return variableNodesWithRegexs.find((varNode) => {
+                if (utils_1.ASTUtils.isVariableDeclarator(varNode) &&
+                    utils_1.ASTUtils.isIdentifier(varNode.id)) {
+                    return varNode.id.name === identifier.name;
+                }
+                return undefined;
+            });
+        }
+        return {
+            VariableDeclarator(node) {
+                if (utils_1.ASTUtils.isVariableDeclarator(node) &&
+                    (0, node_utils_1.isLiteral)(node.init) &&
+                    'regex' in node.init &&
+                    node.init.regex.flags.includes('g')) {
+                    variableNodesWithRegexs.push(node);
+                }
+            },
+            CallExpression(node) {
+                const identifierNode = (0, node_utils_1.getDeepestIdentifierNode)(node);
+                if (!identifierNode || !helpers.isQuery(identifierNode)) {
+                    return;
+                }
+                const [firstArg, secondArg] = getArguments(identifierNode);
+                const firstArgumentHasError = reportLiteralWithRegex(firstArg);
+                if (firstArgumentHasError) {
+                    return;
+                }
+                if (utils_1.ASTUtils.isIdentifier(firstArg)) {
+                    const regexVariableNode = hasRegexInVariable(firstArg);
+                    if (regexVariableNode !== undefined) {
+                        context.report({
+                            node: firstArg,
+                            messageId: 'noGlobalRegExpFlagInQuery',
+                            fix(fixer) {
+                                if (utils_1.ASTUtils.isVariableDeclarator(regexVariableNode) &&
+                                    (0, node_utils_1.isLiteral)(regexVariableNode.init) &&
+                                    'regex' in regexVariableNode.init &&
+                                    regexVariableNode.init.regex.flags.includes('g')) {
+                                    const splitter = regexVariableNode.init.raw.lastIndexOf('/');
+                                    const raw = regexVariableNode.init.raw.substring(0, splitter);
+                                    const flags = regexVariableNode.init.raw.substring(splitter + 1);
+                                    const flagsWithoutGlobal = flags.replace('g', '');
+                                    return fixer.replaceText(regexVariableNode.init, `${raw}/${flagsWithoutGlobal}`);
+                                }
+                                return null;
+                            },
+                        });
+                    }
+                }
+                if ((0, node_utils_1.isObjectExpression)(secondArg)) {
+                    const namePropertyNode = secondArg.properties.find((p) => (0, node_utils_1.isProperty)(p) &&
+                        utils_1.ASTUtils.isIdentifier(p.key) &&
+                        p.key.name === 'name' &&
+                        (0, node_utils_1.isLiteral)(p.value));
+                    if (namePropertyNode) {
+                        reportLiteralWithRegex(namePropertyNode.value);
+                    }
+                }
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/no-manual-cleanup.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/no-manual-cleanup.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/no-manual-cleanup.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,94 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'no-manual-cleanup';
+const CLEANUP_LIBRARY_REGEXP = /(@testing-library\/(preact|react|svelte|vue))|@marko\/testing-library/;
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'problem',
+        docs: {
+            description: 'Disallow the use of `cleanup`',
+            recommendedConfig: {
+                dom: false,
+                angular: false,
+                react: false,
+                vue: false,
+                marko: false,
+            },
+        },
+        messages: {
+            noManualCleanup: "`cleanup` is performed automatically by your test runner, you don't need manual cleanups.",
+        },
+        schema: [],
+    },
+    defaultOptions: [],
+    create(context, _, helpers) {
+        function reportImportReferences(references) {
+            for (const reference of references) {
+                const utilsUsage = reference.identifier.parent;
+                if (utilsUsage &&
+                    (0, node_utils_1.isMemberExpression)(utilsUsage) &&
+                    utils_1.ASTUtils.isIdentifier(utilsUsage.property) &&
+                    utilsUsage.property.name === 'cleanup') {
+                    context.report({
+                        node: utilsUsage.property,
+                        messageId: 'noManualCleanup',
+                    });
+                }
+            }
+        }
+        function reportCandidateModule(moduleNode) {
+            if ((0, node_utils_1.isImportDeclaration)(moduleNode)) {
+                if ((0, node_utils_1.isImportDefaultSpecifier)(moduleNode.specifiers[0])) {
+                    const { references } = context.getDeclaredVariables(moduleNode)[0];
+                    reportImportReferences(references);
+                }
+                const cleanupSpecifier = moduleNode.specifiers.find((specifier) => (0, node_utils_1.isImportSpecifier)(specifier) &&
+                    specifier.imported.name === 'cleanup');
+                if (cleanupSpecifier) {
+                    context.report({
+                        node: cleanupSpecifier,
+                        messageId: 'noManualCleanup',
+                    });
+                }
+            }
+            else {
+                const declaratorNode = moduleNode.parent;
+                if ((0, node_utils_1.isObjectPattern)(declaratorNode.id)) {
+                    const cleanupProperty = declaratorNode.id.properties.find((property) => (0, node_utils_1.isProperty)(property) &&
+                        utils_1.ASTUtils.isIdentifier(property.key) &&
+                        property.key.name === 'cleanup');
+                    if (cleanupProperty) {
+                        context.report({
+                            node: cleanupProperty,
+                            messageId: 'noManualCleanup',
+                        });
+                    }
+                }
+                else {
+                    const references = (0, node_utils_1.getVariableReferences)(context, declaratorNode);
+                    reportImportReferences(references);
+                }
+            }
+        }
+        return {
+            'Program:exit'() {
+                const testingLibraryImportName = helpers.getTestingLibraryImportName();
+                const testingLibraryImportNode = helpers.getTestingLibraryImportNode();
+                const customModuleImportNode = helpers.getCustomModuleImportNode();
+                if (testingLibraryImportName &&
+                    testingLibraryImportNode &&
+                    testingLibraryImportName.match(CLEANUP_LIBRARY_REGEXP)) {
+                    reportCandidateModule(testingLibraryImportNode);
+                }
+                if (customModuleImportNode) {
+                    reportCandidateModule(customModuleImportNode);
+                }
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/no-node-access.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/no-node-access.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/no-node-access.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,67 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const utils_2 = require("../utils");
+exports.RULE_NAME = 'no-node-access';
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'problem',
+        docs: {
+            description: 'Disallow direct Node access',
+            recommendedConfig: {
+                dom: false,
+                angular: 'error',
+                react: 'error',
+                vue: 'error',
+                marko: 'error',
+            },
+        },
+        messages: {
+            noNodeAccess: 'Avoid direct Node access. Prefer using the methods from Testing Library.',
+        },
+        schema: [
+            {
+                type: 'object',
+                properties: {
+                    allowContainerFirstChild: {
+                        type: 'boolean',
+                    },
+                },
+            },
+        ],
+    },
+    defaultOptions: [
+        {
+            allowContainerFirstChild: false,
+        },
+    ],
+    create(context, [{ allowContainerFirstChild = false }], helpers) {
+        function showErrorForNodeAccess(node) {
+            if (!helpers.isTestingLibraryImported(true)) {
+                return;
+            }
+            if (utils_1.ASTUtils.isIdentifier(node.property) &&
+                utils_2.ALL_RETURNING_NODES.includes(node.property.name)) {
+                if (allowContainerFirstChild && node.property.name === 'firstChild') {
+                    return;
+                }
+                if (utils_1.ASTUtils.isIdentifier(node.object) &&
+                    node.object.name === 'props') {
+                    return;
+                }
+                context.report({
+                    node,
+                    loc: node.property.loc.start,
+                    messageId: 'noNodeAccess',
+                });
+            }
+        }
+        return {
+            'ExpressionStatement MemberExpression': showErrorForNodeAccess,
+            'VariableDeclarator MemberExpression': showErrorForNodeAccess,
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/no-promise-in-fire-event.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/no-promise-in-fire-event.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/no-promise-in-fire-event.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,83 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'no-promise-in-fire-event';
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'problem',
+        docs: {
+            description: 'Disallow the use of promises passed to a `fireEvent` method',
+            recommendedConfig: {
+                dom: 'error',
+                angular: 'error',
+                react: 'error',
+                vue: 'error',
+                marko: 'error',
+            },
+        },
+        messages: {
+            noPromiseInFireEvent: "A promise shouldn't be passed to a `fireEvent` method, instead pass the DOM element",
+        },
+        schema: [],
+    },
+    defaultOptions: [],
+    create(context, _, helpers) {
+        function checkSuspiciousNode(node, originalNode) {
+            if (utils_1.ASTUtils.isAwaitExpression(node)) {
+                return;
+            }
+            if ((0, node_utils_1.isNewExpression)(node)) {
+                if ((0, node_utils_1.isPromiseIdentifier)(node.callee)) {
+                    context.report({
+                        node: originalNode !== null && originalNode !== void 0 ? originalNode : node,
+                        messageId: 'noPromiseInFireEvent',
+                    });
+                    return;
+                }
+            }
+            if ((0, node_utils_1.isCallExpression)(node)) {
+                const domElementIdentifier = (0, node_utils_1.getDeepestIdentifierNode)(node);
+                if (!domElementIdentifier) {
+                    return;
+                }
+                if (helpers.isAsyncQuery(domElementIdentifier) ||
+                    (0, node_utils_1.isPromiseIdentifier)(domElementIdentifier)) {
+                    context.report({
+                        node: originalNode !== null && originalNode !== void 0 ? originalNode : node,
+                        messageId: 'noPromiseInFireEvent',
+                    });
+                    return;
+                }
+            }
+            if (utils_1.ASTUtils.isIdentifier(node)) {
+                const nodeVariable = utils_1.ASTUtils.findVariable(context.getScope(), node.name);
+                if (!nodeVariable) {
+                    return;
+                }
+                for (const definition of nodeVariable.defs) {
+                    const variableDeclarator = definition.node;
+                    if (variableDeclarator.init) {
+                        checkSuspiciousNode(variableDeclarator.init, node);
+                    }
+                }
+            }
+        }
+        return {
+            'CallExpression Identifier'(node) {
+                if (!helpers.isFireEventMethod(node)) {
+                    return;
+                }
+                const closestCallExpression = (0, node_utils_1.findClosestCallExpressionNode)(node, true);
+                if (!closestCallExpression) {
+                    return;
+                }
+                const domElementArgument = closestCallExpression.arguments[0];
+                checkSuspiciousNode(domElementArgument);
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/no-render-in-setup.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/no-render-in-setup.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/no-render-in-setup.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,94 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.findClosestBeforeHook = exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+const utils_2 = require("../utils");
+exports.RULE_NAME = 'no-render-in-setup';
+function findClosestBeforeHook(node, testingFrameworkSetupHooksToFilter) {
+    if (node === null) {
+        return null;
+    }
+    if ((0, node_utils_1.isCallExpression)(node) &&
+        utils_1.ASTUtils.isIdentifier(node.callee) &&
+        testingFrameworkSetupHooksToFilter.includes(node.callee.name)) {
+        return node.callee;
+    }
+    if (node.parent) {
+        return findClosestBeforeHook(node.parent, testingFrameworkSetupHooksToFilter);
+    }
+    return null;
+}
+exports.findClosestBeforeHook = findClosestBeforeHook;
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'problem',
+        docs: {
+            description: 'Disallow the use of `render` in testing frameworks setup functions',
+            recommendedConfig: {
+                dom: false,
+                angular: 'error',
+                react: 'error',
+                vue: 'error',
+                marko: 'error',
+            },
+        },
+        messages: {
+            noRenderInSetup: 'Forbidden usage of `render` within testing framework `{{ name }}` setup',
+        },
+        schema: [
+            {
+                type: 'object',
+                properties: {
+                    allowTestingFrameworkSetupHook: {
+                        enum: utils_2.TESTING_FRAMEWORK_SETUP_HOOKS,
+                    },
+                },
+            },
+        ],
+    },
+    defaultOptions: [
+        {
+            allowTestingFrameworkSetupHook: '',
+        },
+    ],
+    create(context, [{ allowTestingFrameworkSetupHook }], helpers) {
+        const renderWrapperNames = [];
+        function detectRenderWrapper(node) {
+            const innerFunction = (0, node_utils_1.getInnermostReturningFunction)(context, node);
+            if (innerFunction) {
+                renderWrapperNames.push((0, node_utils_1.getFunctionName)(innerFunction));
+            }
+        }
+        return {
+            CallExpression(node) {
+                const testingFrameworkSetupHooksToFilter = utils_2.TESTING_FRAMEWORK_SETUP_HOOKS.filter((hook) => hook !== allowTestingFrameworkSetupHook);
+                const callExpressionIdentifier = (0, node_utils_1.getDeepestIdentifierNode)(node);
+                if (!callExpressionIdentifier) {
+                    return;
+                }
+                const isRenderIdentifier = helpers.isRenderUtil(callExpressionIdentifier);
+                if (isRenderIdentifier) {
+                    detectRenderWrapper(callExpressionIdentifier);
+                }
+                if (!isRenderIdentifier &&
+                    !renderWrapperNames.includes(callExpressionIdentifier.name)) {
+                    return;
+                }
+                const beforeHook = findClosestBeforeHook(node, testingFrameworkSetupHooksToFilter);
+                if (!beforeHook) {
+                    return;
+                }
+                context.report({
+                    node: callExpressionIdentifier,
+                    messageId: 'noRenderInSetup',
+                    data: {
+                        name: beforeHook.name,
+                    },
+                });
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/no-unnecessary-act.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/no-unnecessary-act.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/no-unnecessary-act.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,141 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'no-unnecessary-act';
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'problem',
+        docs: {
+            description: 'Disallow wrapping Testing Library utils or empty callbacks in `act`',
+            recommendedConfig: {
+                dom: false,
+                angular: false,
+                react: 'error',
+                vue: false,
+                marko: 'error',
+            },
+        },
+        messages: {
+            noUnnecessaryActTestingLibraryUtil: 'Avoid wrapping Testing Library util calls in `act`',
+            noUnnecessaryActEmptyFunction: 'Avoid wrapping empty function in `act`',
+        },
+        schema: [
+            {
+                type: 'object',
+                properties: {
+                    isStrict: {
+                        type: 'boolean',
+                    },
+                },
+            },
+        ],
+    },
+    defaultOptions: [
+        {
+            isStrict: true,
+        },
+    ],
+    create(context, [{ isStrict = true }], helpers) {
+        function getStatementIdentifier(statement) {
+            const callExpression = (0, node_utils_1.getStatementCallExpression)(statement);
+            if (!callExpression &&
+                !(0, node_utils_1.isExpressionStatement)(statement) &&
+                !(0, node_utils_1.isReturnStatement)(statement)) {
+                return null;
+            }
+            if (callExpression) {
+                return (0, node_utils_1.getDeepestIdentifierNode)(callExpression);
+            }
+            if ((0, node_utils_1.isExpressionStatement)(statement) &&
+                utils_1.ASTUtils.isAwaitExpression(statement.expression)) {
+                return (0, node_utils_1.getPropertyIdentifierNode)(statement.expression.argument);
+            }
+            if ((0, node_utils_1.isReturnStatement)(statement) && statement.argument) {
+                return (0, node_utils_1.getPropertyIdentifierNode)(statement.argument);
+            }
+            return null;
+        }
+        function hasSomeNonTestingLibraryCall(statements) {
+            return statements.some((statement) => {
+                const identifier = getStatementIdentifier(statement);
+                if (!identifier) {
+                    return false;
+                }
+                return !helpers.isTestingLibraryUtil(identifier);
+            });
+        }
+        function hasTestingLibraryCall(statements) {
+            return statements.some((statement) => {
+                const identifier = getStatementIdentifier(statement);
+                if (!identifier) {
+                    return false;
+                }
+                return helpers.isTestingLibraryUtil(identifier);
+            });
+        }
+        function checkNoUnnecessaryActFromBlockStatement(blockStatementNode) {
+            const functionNode = blockStatementNode.parent;
+            const callExpressionNode = functionNode === null || functionNode === void 0 ? void 0 : functionNode.parent;
+            if (!callExpressionNode || !functionNode) {
+                return;
+            }
+            const identifierNode = (0, node_utils_1.getDeepestIdentifierNode)(callExpressionNode);
+            if (!identifierNode) {
+                return;
+            }
+            if (!helpers.isActUtil(identifierNode)) {
+                return;
+            }
+            if ((0, node_utils_1.isEmptyFunction)(functionNode)) {
+                context.report({
+                    node: identifierNode,
+                    messageId: 'noUnnecessaryActEmptyFunction',
+                });
+                return;
+            }
+            const shouldBeReported = isStrict
+                ? hasTestingLibraryCall(blockStatementNode.body)
+                : !hasSomeNonTestingLibraryCall(blockStatementNode.body);
+            if (shouldBeReported) {
+                context.report({
+                    node: identifierNode,
+                    messageId: 'noUnnecessaryActTestingLibraryUtil',
+                });
+            }
+        }
+        function checkNoUnnecessaryActFromImplicitReturn(node) {
+            var _a;
+            const nodeIdentifier = (0, node_utils_1.getDeepestIdentifierNode)(node);
+            if (!nodeIdentifier) {
+                return;
+            }
+            const parentCallExpression = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent;
+            if (!parentCallExpression) {
+                return;
+            }
+            const identifierNode = (0, node_utils_1.getDeepestIdentifierNode)(parentCallExpression);
+            if (!identifierNode) {
+                return;
+            }
+            if (!helpers.isActUtil(identifierNode)) {
+                return;
+            }
+            if (!helpers.isTestingLibraryUtil(nodeIdentifier)) {
+                return;
+            }
+            context.report({
+                node: identifierNode,
+                messageId: 'noUnnecessaryActTestingLibraryUtil',
+            });
+        }
+        return {
+            'CallExpression > ArrowFunctionExpression > BlockStatement': checkNoUnnecessaryActFromBlockStatement,
+            'CallExpression > FunctionExpression > BlockStatement': checkNoUnnecessaryActFromBlockStatement,
+            'CallExpression > ArrowFunctionExpression > CallExpression': checkNoUnnecessaryActFromImplicitReturn,
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/no-wait-for-empty-callback.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/no-wait-for-empty-callback.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/no-wait-for-empty-callback.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,78 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'no-wait-for-empty-callback';
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'suggestion',
+        docs: {
+            description: 'Disallow empty callbacks for `waitFor` and `waitForElementToBeRemoved`',
+            recommendedConfig: {
+                dom: 'error',
+                angular: 'error',
+                react: 'error',
+                vue: 'error',
+                marko: 'error',
+            },
+        },
+        messages: {
+            noWaitForEmptyCallback: 'Avoid passing empty callback to `{{ methodName }}`. Insert an assertion instead.',
+        },
+        schema: [],
+    },
+    defaultOptions: [],
+    create(context, _, helpers) {
+        function isValidWaitFor(node) {
+            const parentCallExpression = node.parent;
+            const parentIdentifier = (0, node_utils_1.getPropertyIdentifierNode)(parentCallExpression);
+            if (!parentIdentifier) {
+                return false;
+            }
+            return helpers.isAsyncUtil(parentIdentifier, [
+                'waitFor',
+                'waitForElementToBeRemoved',
+            ]);
+        }
+        function reportIfEmpty(node) {
+            if (!isValidWaitFor(node)) {
+                return;
+            }
+            if ((0, node_utils_1.isEmptyFunction)(node) &&
+                (0, node_utils_1.isCallExpression)(node.parent) &&
+                utils_1.ASTUtils.isIdentifier(node.parent.callee)) {
+                context.report({
+                    node,
+                    loc: node.body.loc.start,
+                    messageId: 'noWaitForEmptyCallback',
+                    data: {
+                        methodName: node.parent.callee.name,
+                    },
+                });
+            }
+        }
+        function reportNoop(node) {
+            if (!isValidWaitFor(node)) {
+                return;
+            }
+            context.report({
+                node,
+                loc: node.loc.start,
+                messageId: 'noWaitForEmptyCallback',
+                data: {
+                    methodName: (0, node_utils_1.isCallExpression)(node.parent) &&
+                        utils_1.ASTUtils.isIdentifier(node.parent.callee) &&
+                        node.parent.callee.name,
+                },
+            });
+        }
+        return {
+            'CallExpression > ArrowFunctionExpression': reportIfEmpty,
+            'CallExpression > FunctionExpression': reportIfEmpty,
+            'CallExpression > Identifier[name="noop"]': reportNoop,
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/no-wait-for-multiple-assertions.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/no-wait-for-multiple-assertions.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/no-wait-for-multiple-assertions.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,70 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'no-wait-for-multiple-assertions';
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'suggestion',
+        docs: {
+            description: 'Disallow the use of multiple `expect` calls inside `waitFor`',
+            recommendedConfig: {
+                dom: 'error',
+                angular: 'error',
+                react: 'error',
+                vue: 'error',
+                marko: 'error',
+            },
+        },
+        messages: {
+            noWaitForMultipleAssertion: 'Avoid using multiple assertions within `waitFor` callback',
+        },
+        schema: [],
+    },
+    defaultOptions: [],
+    create(context, _, helpers) {
+        function getExpectNodes(body) {
+            return body.filter((node) => {
+                if (!(0, node_utils_1.isExpressionStatement)(node)) {
+                    return false;
+                }
+                const expressionIdentifier = (0, node_utils_1.getPropertyIdentifierNode)(node);
+                if (!expressionIdentifier) {
+                    return false;
+                }
+                return expressionIdentifier.name === 'expect';
+            });
+        }
+        function reportMultipleAssertion(node) {
+            if (!node.parent) {
+                return;
+            }
+            const callExpressionNode = node.parent.parent;
+            const callExpressionIdentifier = (0, node_utils_1.getPropertyIdentifierNode)(callExpressionNode);
+            if (!callExpressionIdentifier) {
+                return;
+            }
+            if (!helpers.isAsyncUtil(callExpressionIdentifier, ['waitFor'])) {
+                return;
+            }
+            const expectNodes = getExpectNodes(node.body);
+            if (expectNodes.length <= 1) {
+                return;
+            }
+            for (let i = 0; i < expectNodes.length; i++) {
+                if (i !== 0) {
+                    context.report({
+                        node: expectNodes[i],
+                        messageId: 'noWaitForMultipleAssertion',
+                    });
+                }
+            }
+        }
+        return {
+            'CallExpression > ArrowFunctionExpression > BlockStatement': reportMultipleAssertion,
+            'CallExpression > FunctionExpression > BlockStatement': reportMultipleAssertion,
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/no-wait-for-side-effects.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/no-wait-for-side-effects.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/no-wait-for-side-effects.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,155 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'no-wait-for-side-effects';
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'suggestion',
+        docs: {
+            description: 'Disallow the use of side effects in `waitFor`',
+            recommendedConfig: {
+                dom: 'error',
+                angular: 'error',
+                react: 'error',
+                vue: 'error',
+                marko: 'error',
+            },
+        },
+        messages: {
+            noSideEffectsWaitFor: 'Avoid using side effects within `waitFor` callback',
+        },
+        schema: [],
+    },
+    defaultOptions: [],
+    create(context, _, helpers) {
+        function isCallerWaitFor(node) {
+            if (!node.parent) {
+                return false;
+            }
+            const callExpressionNode = node.parent.parent;
+            const callExpressionIdentifier = (0, node_utils_1.getPropertyIdentifierNode)(callExpressionNode);
+            return (!!callExpressionIdentifier &&
+                helpers.isAsyncUtil(callExpressionIdentifier, ['waitFor']));
+        }
+        function isCallerThen(node) {
+            if (!node.parent) {
+                return false;
+            }
+            const callExpressionNode = node.parent.parent;
+            return (0, node_utils_1.hasThenProperty)(callExpressionNode.callee);
+        }
+        function isRenderInVariableDeclaration(node) {
+            return ((0, node_utils_1.isVariableDeclaration)(node) &&
+                node.declarations.some(helpers.isRenderVariableDeclarator));
+        }
+        function isRenderInExpressionStatement(node) {
+            if (!(0, node_utils_1.isExpressionStatement)(node) ||
+                !(0, node_utils_1.isAssignmentExpression)(node.expression)) {
+                return false;
+            }
+            const expressionIdentifier = (0, node_utils_1.getPropertyIdentifierNode)(node.expression.right);
+            if (!expressionIdentifier) {
+                return false;
+            }
+            return helpers.isRenderUtil(expressionIdentifier);
+        }
+        function isRenderInAssignmentExpression(node) {
+            if (!(0, node_utils_1.isAssignmentExpression)(node)) {
+                return false;
+            }
+            const expressionIdentifier = (0, node_utils_1.getPropertyIdentifierNode)(node.right);
+            if (!expressionIdentifier) {
+                return false;
+            }
+            return helpers.isRenderUtil(expressionIdentifier);
+        }
+        function isRenderInSequenceAssignment(node) {
+            if (!(0, node_utils_1.isSequenceExpression)(node)) {
+                return false;
+            }
+            return node.expressions.some(isRenderInAssignmentExpression);
+        }
+        function isSideEffectInVariableDeclaration(node) {
+            return node.declarations.some((declaration) => {
+                if ((0, node_utils_1.isCallExpression)(declaration.init)) {
+                    const test = (0, node_utils_1.getPropertyIdentifierNode)(declaration.init);
+                    if (!test) {
+                        return false;
+                    }
+                    return (helpers.isFireEventUtil(test) ||
+                        helpers.isUserEventUtil(test) ||
+                        helpers.isRenderUtil(test));
+                }
+                return false;
+            });
+            return false;
+        }
+        function getSideEffectNodes(body) {
+            return body.filter((node) => {
+                if (!(0, node_utils_1.isExpressionStatement)(node) && !(0, node_utils_1.isVariableDeclaration)(node)) {
+                    return false;
+                }
+                if (isRenderInVariableDeclaration(node) ||
+                    isRenderInExpressionStatement(node)) {
+                    return true;
+                }
+                if ((0, node_utils_1.isVariableDeclaration)(node) &&
+                    isSideEffectInVariableDeclaration(node)) {
+                    return true;
+                }
+                const expressionIdentifier = (0, node_utils_1.getPropertyIdentifierNode)(node);
+                if (!expressionIdentifier) {
+                    return false;
+                }
+                return (helpers.isFireEventUtil(expressionIdentifier) ||
+                    helpers.isUserEventUtil(expressionIdentifier) ||
+                    helpers.isRenderUtil(expressionIdentifier));
+            });
+        }
+        function reportSideEffects(node) {
+            if (!isCallerWaitFor(node)) {
+                return;
+            }
+            if (isCallerThen(node)) {
+                return;
+            }
+            getSideEffectNodes(node.body).forEach((sideEffectNode) => context.report({
+                node: sideEffectNode,
+                messageId: 'noSideEffectsWaitFor',
+            }));
+        }
+        function reportImplicitReturnSideEffect(node) {
+            if (!isCallerWaitFor(node)) {
+                return;
+            }
+            const expressionIdentifier = (0, node_utils_1.isCallExpression)(node)
+                ? (0, node_utils_1.getPropertyIdentifierNode)(node.callee)
+                : null;
+            if (!expressionIdentifier &&
+                !isRenderInAssignmentExpression(node) &&
+                !isRenderInSequenceAssignment(node)) {
+                return;
+            }
+            if (expressionIdentifier &&
+                !helpers.isFireEventUtil(expressionIdentifier) &&
+                !helpers.isUserEventUtil(expressionIdentifier) &&
+                !helpers.isRenderUtil(expressionIdentifier)) {
+                return;
+            }
+            context.report({
+                node,
+                messageId: 'noSideEffectsWaitFor',
+            });
+        }
+        return {
+            'CallExpression > ArrowFunctionExpression > BlockStatement': reportSideEffects,
+            'CallExpression > ArrowFunctionExpression > CallExpression': reportImplicitReturnSideEffect,
+            'CallExpression > ArrowFunctionExpression > AssignmentExpression': reportImplicitReturnSideEffect,
+            'CallExpression > ArrowFunctionExpression > SequenceExpression': reportImplicitReturnSideEffect,
+            'CallExpression > FunctionExpression > BlockStatement': reportSideEffects,
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/no-wait-for-snapshot.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/no-wait-for-snapshot.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/no-wait-for-snapshot.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,66 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'no-wait-for-snapshot';
+const SNAPSHOT_REGEXP = /^(toMatchSnapshot|toMatchInlineSnapshot)$/;
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'problem',
+        docs: {
+            description: 'Ensures no snapshot is generated inside of a `waitFor` call',
+            recommendedConfig: {
+                dom: 'error',
+                angular: 'error',
+                react: 'error',
+                vue: 'error',
+                marko: 'error',
+            },
+        },
+        messages: {
+            noWaitForSnapshot: "A snapshot can't be generated inside of a `{{ name }}` call",
+        },
+        schema: [],
+    },
+    defaultOptions: [],
+    create(context, _, helpers) {
+        function getClosestAsyncUtil(node) {
+            let n = node;
+            do {
+                const callExpression = (0, node_utils_1.findClosestCallExpressionNode)(n);
+                if (!callExpression) {
+                    return null;
+                }
+                if (utils_1.ASTUtils.isIdentifier(callExpression.callee) &&
+                    helpers.isAsyncUtil(callExpression.callee)) {
+                    return callExpression.callee;
+                }
+                if ((0, node_utils_1.isMemberExpression)(callExpression.callee) &&
+                    utils_1.ASTUtils.isIdentifier(callExpression.callee.property) &&
+                    helpers.isAsyncUtil(callExpression.callee.property)) {
+                    return callExpression.callee.property;
+                }
+                if (callExpression.parent) {
+                    n = (0, node_utils_1.findClosestCallExpressionNode)(callExpression.parent);
+                }
+            } while (n !== null);
+            return null;
+        }
+        return {
+            [`Identifier[name=${String(SNAPSHOT_REGEXP)}]`](node) {
+                const closestAsyncUtil = getClosestAsyncUtil(node);
+                if (closestAsyncUtil === null) {
+                    return;
+                }
+                context.report({
+                    node,
+                    messageId: 'noWaitForSnapshot',
+                    data: { name: closestAsyncUtil.name },
+                });
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/prefer-explicit-assert.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/prefer-explicit-assert.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/prefer-explicit-assert.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,154 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+const utils_2 = require("../utils");
+exports.RULE_NAME = 'prefer-explicit-assert';
+const isAtTopLevel = (node) => {
+    var _a, _b, _c;
+    return (!!((_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent) &&
+        node.parent.parent.type === 'ExpressionStatement') ||
+        (((_c = (_b = node.parent) === null || _b === void 0 ? void 0 : _b.parent) === null || _c === void 0 ? void 0 : _c.type) === 'AwaitExpression' &&
+            !!node.parent.parent.parent &&
+            node.parent.parent.parent.type === 'ExpressionStatement');
+};
+const isVariableDeclaration = (node) => {
+    if ((0, node_utils_1.isCallExpression)(node.parent) &&
+        utils_1.ASTUtils.isAwaitExpression(node.parent.parent) &&
+        utils_1.ASTUtils.isVariableDeclarator(node.parent.parent.parent)) {
+        return true;
+    }
+    if ((0, node_utils_1.isCallExpression)(node.parent) &&
+        utils_1.ASTUtils.isVariableDeclarator(node.parent.parent)) {
+        return true;
+    }
+    if ((0, node_utils_1.isMemberExpression)(node.parent) &&
+        (0, node_utils_1.isCallExpression)(node.parent.parent) &&
+        utils_1.ASTUtils.isAwaitExpression(node.parent.parent.parent) &&
+        utils_1.ASTUtils.isVariableDeclarator(node.parent.parent.parent.parent)) {
+        return true;
+    }
+    if ((0, node_utils_1.isMemberExpression)(node.parent) &&
+        (0, node_utils_1.isCallExpression)(node.parent.parent) &&
+        utils_1.ASTUtils.isVariableDeclarator(node.parent.parent.parent)) {
+        return true;
+    }
+    return false;
+};
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'suggestion',
+        docs: {
+            description: 'Suggest using explicit assertions rather than standalone queries',
+            recommendedConfig: {
+                dom: false,
+                angular: false,
+                react: false,
+                vue: false,
+                marko: false,
+            },
+        },
+        messages: {
+            preferExplicitAssert: 'Wrap stand-alone `{{queryType}}` query with `expect` function for better explicit assertion',
+            preferExplicitAssertAssertion: '`getBy*` queries must be asserted with `{{assertion}}`',
+        },
+        schema: [
+            {
+                type: 'object',
+                additionalProperties: false,
+                properties: {
+                    assertion: {
+                        type: 'string',
+                        enum: utils_2.PRESENCE_MATCHERS,
+                    },
+                    includeFindQueries: { type: 'boolean' },
+                },
+            },
+        ],
+    },
+    defaultOptions: [{ includeFindQueries: true }],
+    create(context, [options], helpers) {
+        const { assertion, includeFindQueries } = options;
+        const getQueryCalls = [];
+        const findQueryCalls = [];
+        return {
+            'CallExpression Identifier'(node) {
+                if (helpers.isGetQueryVariant(node)) {
+                    getQueryCalls.push(node);
+                }
+                if (helpers.isFindQueryVariant(node)) {
+                    findQueryCalls.push(node);
+                }
+            },
+            'Program:exit'() {
+                if (includeFindQueries) {
+                    findQueryCalls.forEach((queryCall) => {
+                        const memberExpression = (0, node_utils_1.isMemberExpression)(queryCall.parent)
+                            ? queryCall.parent
+                            : queryCall;
+                        if (isVariableDeclaration(queryCall) ||
+                            !isAtTopLevel(memberExpression)) {
+                            return;
+                        }
+                        context.report({
+                            node: queryCall,
+                            messageId: 'preferExplicitAssert',
+                            data: {
+                                queryType: 'findBy*',
+                            },
+                        });
+                    });
+                }
+                getQueryCalls.forEach((queryCall) => {
+                    const node = (0, node_utils_1.isMemberExpression)(queryCall.parent)
+                        ? queryCall.parent
+                        : queryCall;
+                    if (isAtTopLevel(node)) {
+                        context.report({
+                            node: queryCall,
+                            messageId: 'preferExplicitAssert',
+                            data: {
+                                queryType: 'getBy*',
+                            },
+                        });
+                    }
+                    if (assertion) {
+                        const expectCallNode = (0, node_utils_1.findClosestCallNode)(node, 'expect');
+                        if (!expectCallNode)
+                            return;
+                        const expectStatement = expectCallNode.parent;
+                        if (!(0, node_utils_1.isMemberExpression)(expectStatement)) {
+                            return;
+                        }
+                        const property = expectStatement.property;
+                        if (!utils_1.ASTUtils.isIdentifier(property)) {
+                            return;
+                        }
+                        let matcher = property.name;
+                        let isNegatedMatcher = false;
+                        if (matcher === 'not' &&
+                            (0, node_utils_1.isMemberExpression)(expectStatement.parent) &&
+                            utils_1.ASTUtils.isIdentifier(expectStatement.parent.property)) {
+                            isNegatedMatcher = true;
+                            matcher = expectStatement.parent.property.name;
+                        }
+                        const shouldEnforceAssertion = (!isNegatedMatcher && utils_2.PRESENCE_MATCHERS.includes(matcher)) ||
+                            (isNegatedMatcher && utils_2.ABSENCE_MATCHERS.includes(matcher));
+                        if (shouldEnforceAssertion && matcher !== assertion) {
+                            context.report({
+                                node: property,
+                                messageId: 'preferExplicitAssertAssertion',
+                                data: {
+                                    assertion,
+                                },
+                            });
+                        }
+                    }
+                });
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/prefer-find-by.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/prefer-find-by.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/prefer-find-by.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,293 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.getFindByQueryVariant = exports.WAIT_METHODS = exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'prefer-find-by';
+exports.WAIT_METHODS = ['waitFor', 'waitForElement', 'wait'];
+function getFindByQueryVariant(queryMethod) {
+    return queryMethod.includes('All') ? 'findAllBy' : 'findBy';
+}
+exports.getFindByQueryVariant = getFindByQueryVariant;
+function findRenderDefinitionDeclaration(scope, query) {
+    var _a;
+    if (!scope) {
+        return null;
+    }
+    const variable = scope.variables.find((v) => v.name === query);
+    if (variable) {
+        return ((_a = variable.defs
+            .map(({ name }) => name)
+            .filter(utils_1.ASTUtils.isIdentifier)
+            .find(({ name }) => name === query)) !== null && _a !== void 0 ? _a : null);
+    }
+    return findRenderDefinitionDeclaration(scope.upper, query);
+}
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'suggestion',
+        docs: {
+            description: 'Suggest using `find(All)By*` query instead of `waitFor` + `get(All)By*` to wait for elements',
+            recommendedConfig: {
+                dom: 'error',
+                angular: 'error',
+                react: 'error',
+                vue: 'error',
+                marko: 'error',
+            },
+        },
+        messages: {
+            preferFindBy: 'Prefer `{{queryVariant}}{{queryMethod}}` query over using `{{waitForMethodName}}` + `{{prevQuery}}`',
+        },
+        fixable: 'code',
+        schema: [],
+    },
+    defaultOptions: [],
+    create(context, _, helpers) {
+        const sourceCode = context.getSourceCode();
+        function reportInvalidUsage(node, replacementParams) {
+            const { queryMethod, queryVariant, prevQuery, waitForMethodName, fix } = replacementParams;
+            context.report({
+                node,
+                messageId: 'preferFindBy',
+                data: {
+                    queryVariant,
+                    queryMethod,
+                    prevQuery,
+                    waitForMethodName,
+                },
+                fix,
+            });
+        }
+        function getWrongQueryNameInAssertion(node) {
+            if (!(0, node_utils_1.isCallExpression)(node.body) ||
+                !(0, node_utils_1.isMemberExpression)(node.body.callee)) {
+                return null;
+            }
+            if ((0, node_utils_1.isCallExpression)(node.body.callee.object) &&
+                (0, node_utils_1.isCallExpression)(node.body.callee.object.arguments[0]) &&
+                utils_1.ASTUtils.isIdentifier(node.body.callee.object.arguments[0].callee)) {
+                return node.body.callee.object.arguments[0].callee.name;
+            }
+            if (!utils_1.ASTUtils.isIdentifier(node.body.callee.property)) {
+                return null;
+            }
+            if ((0, node_utils_1.isCallExpression)(node.body.callee.object) &&
+                (0, node_utils_1.isCallExpression)(node.body.callee.object.arguments[0]) &&
+                (0, node_utils_1.isMemberExpression)(node.body.callee.object.arguments[0].callee) &&
+                utils_1.ASTUtils.isIdentifier(node.body.callee.object.arguments[0].callee.property)) {
+                return node.body.callee.object.arguments[0].callee.property.name;
+            }
+            if ((0, node_utils_1.isMemberExpression)(node.body.callee.object) &&
+                (0, node_utils_1.isCallExpression)(node.body.callee.object.object) &&
+                (0, node_utils_1.isCallExpression)(node.body.callee.object.object.arguments[0]) &&
+                (0, node_utils_1.isMemberExpression)(node.body.callee.object.object.arguments[0].callee) &&
+                utils_1.ASTUtils.isIdentifier(node.body.callee.object.object.arguments[0].callee.property)) {
+                return node.body.callee.object.object.arguments[0].callee.property.name;
+            }
+            if ((0, node_utils_1.isMemberExpression)(node.body.callee.object) &&
+                (0, node_utils_1.isCallExpression)(node.body.callee.object.object) &&
+                (0, node_utils_1.isCallExpression)(node.body.callee.object.object.arguments[0]) &&
+                utils_1.ASTUtils.isIdentifier(node.body.callee.object.object.arguments[0].callee)) {
+                return node.body.callee.object.object.arguments[0].callee.name;
+            }
+            return node.body.callee.property.name;
+        }
+        function getWrongQueryName(node) {
+            if (!(0, node_utils_1.isCallExpression)(node.body)) {
+                return null;
+            }
+            if (utils_1.ASTUtils.isIdentifier(node.body.callee) &&
+                helpers.isSyncQuery(node.body.callee)) {
+                return node.body.callee.name;
+            }
+            return getWrongQueryNameInAssertion(node);
+        }
+        function getCaller(node) {
+            if (!(0, node_utils_1.isCallExpression)(node.body) ||
+                !(0, node_utils_1.isMemberExpression)(node.body.callee)) {
+                return null;
+            }
+            if (utils_1.ASTUtils.isIdentifier(node.body.callee.object)) {
+                return node.body.callee.object.name;
+            }
+            if ((0, node_utils_1.isCallExpression)(node.body.callee.object) &&
+                utils_1.ASTUtils.isIdentifier(node.body.callee.object.callee) &&
+                (0, node_utils_1.isCallExpression)(node.body.callee.object.arguments[0]) &&
+                (0, node_utils_1.isMemberExpression)(node.body.callee.object.arguments[0].callee) &&
+                utils_1.ASTUtils.isIdentifier(node.body.callee.object.arguments[0].callee.object)) {
+                return node.body.callee.object.arguments[0].callee.object.name;
+            }
+            if ((0, node_utils_1.isMemberExpression)(node.body.callee.object) &&
+                (0, node_utils_1.isCallExpression)(node.body.callee.object.object) &&
+                (0, node_utils_1.isCallExpression)(node.body.callee.object.object.arguments[0]) &&
+                (0, node_utils_1.isMemberExpression)(node.body.callee.object.object.arguments[0].callee) &&
+                utils_1.ASTUtils.isIdentifier(node.body.callee.object.object.arguments[0].callee.object)) {
+                return node.body.callee.object.object.arguments[0].callee.object.name;
+            }
+            return null;
+        }
+        function isSyncQuery(node) {
+            if (!(0, node_utils_1.isCallExpression)(node.body)) {
+                return false;
+            }
+            const isQuery = utils_1.ASTUtils.isIdentifier(node.body.callee) &&
+                helpers.isSyncQuery(node.body.callee);
+            const isWrappedInPresenceAssert = (0, node_utils_1.isMemberExpression)(node.body.callee) &&
+                (0, node_utils_1.isCallExpression)(node.body.callee.object) &&
+                (0, node_utils_1.isCallExpression)(node.body.callee.object.arguments[0]) &&
+                utils_1.ASTUtils.isIdentifier(node.body.callee.object.arguments[0].callee) &&
+                helpers.isSyncQuery(node.body.callee.object.arguments[0].callee) &&
+                helpers.isPresenceAssert(node.body.callee);
+            const isWrappedInNegatedPresenceAssert = (0, node_utils_1.isMemberExpression)(node.body.callee) &&
+                (0, node_utils_1.isMemberExpression)(node.body.callee.object) &&
+                (0, node_utils_1.isCallExpression)(node.body.callee.object.object) &&
+                (0, node_utils_1.isCallExpression)(node.body.callee.object.object.arguments[0]) &&
+                utils_1.ASTUtils.isIdentifier(node.body.callee.object.object.arguments[0].callee) &&
+                helpers.isSyncQuery(node.body.callee.object.object.arguments[0].callee) &&
+                helpers.isPresenceAssert(node.body.callee.object);
+            return (isQuery || isWrappedInPresenceAssert || isWrappedInNegatedPresenceAssert);
+        }
+        function isScreenSyncQuery(node) {
+            if (!(0, node_utils_1.isArrowFunctionExpression)(node) || !(0, node_utils_1.isCallExpression)(node.body)) {
+                return false;
+            }
+            if (!(0, node_utils_1.isMemberExpression)(node.body.callee) ||
+                !utils_1.ASTUtils.isIdentifier(node.body.callee.property)) {
+                return false;
+            }
+            if (!utils_1.ASTUtils.isIdentifier(node.body.callee.object) &&
+                !(0, node_utils_1.isCallExpression)(node.body.callee.object) &&
+                !(0, node_utils_1.isMemberExpression)(node.body.callee.object)) {
+                return false;
+            }
+            const isWrappedInPresenceAssert = helpers.isPresenceAssert(node.body.callee) &&
+                (0, node_utils_1.isCallExpression)(node.body.callee.object) &&
+                (0, node_utils_1.isCallExpression)(node.body.callee.object.arguments[0]) &&
+                (0, node_utils_1.isMemberExpression)(node.body.callee.object.arguments[0].callee) &&
+                utils_1.ASTUtils.isIdentifier(node.body.callee.object.arguments[0].callee.object);
+            const isWrappedInNegatedPresenceAssert = (0, node_utils_1.isMemberExpression)(node.body.callee.object) &&
+                helpers.isPresenceAssert(node.body.callee.object) &&
+                (0, node_utils_1.isCallExpression)(node.body.callee.object.object) &&
+                (0, node_utils_1.isCallExpression)(node.body.callee.object.object.arguments[0]) &&
+                (0, node_utils_1.isMemberExpression)(node.body.callee.object.object.arguments[0].callee);
+            return (helpers.isSyncQuery(node.body.callee.property) ||
+                isWrappedInPresenceAssert ||
+                isWrappedInNegatedPresenceAssert);
+        }
+        function getQueryArguments(node) {
+            if ((0, node_utils_1.isMemberExpression)(node.callee) &&
+                (0, node_utils_1.isCallExpression)(node.callee.object) &&
+                (0, node_utils_1.isCallExpression)(node.callee.object.arguments[0])) {
+                return node.callee.object.arguments[0].arguments;
+            }
+            if ((0, node_utils_1.isMemberExpression)(node.callee) &&
+                (0, node_utils_1.isMemberExpression)(node.callee.object) &&
+                (0, node_utils_1.isCallExpression)(node.callee.object.object) &&
+                (0, node_utils_1.isCallExpression)(node.callee.object.object.arguments[0])) {
+                return node.callee.object.object.arguments[0].arguments;
+            }
+            return node.arguments;
+        }
+        return {
+            'AwaitExpression > CallExpression'(node) {
+                if (!utils_1.ASTUtils.isIdentifier(node.callee) ||
+                    !helpers.isAsyncUtil(node.callee, exports.WAIT_METHODS)) {
+                    return;
+                }
+                const argument = node.arguments[0];
+                if (!(0, node_utils_1.isArrowFunctionExpression)(argument) ||
+                    !(0, node_utils_1.isCallExpression)(argument.body)) {
+                    return;
+                }
+                const waitForMethodName = node.callee.name;
+                if (isScreenSyncQuery(argument)) {
+                    const caller = getCaller(argument);
+                    if (!caller) {
+                        return;
+                    }
+                    const fullQueryMethod = getWrongQueryName(argument);
+                    if (!fullQueryMethod) {
+                        return;
+                    }
+                    const waitOptions = node.arguments[1];
+                    let waitOptionsSourceCode = '';
+                    if ((0, node_utils_1.isObjectExpression)(waitOptions)) {
+                        waitOptionsSourceCode = `, ${sourceCode.getText(waitOptions)}`;
+                    }
+                    const queryVariant = getFindByQueryVariant(fullQueryMethod);
+                    const callArguments = getQueryArguments(argument.body);
+                    const queryMethod = fullQueryMethod.split('By')[1];
+                    if (!queryMethod) {
+                        return;
+                    }
+                    reportInvalidUsage(node, {
+                        queryMethod,
+                        queryVariant,
+                        prevQuery: fullQueryMethod,
+                        waitForMethodName,
+                        fix(fixer) {
+                            const property = argument.body
+                                .callee.property;
+                            if (helpers.isCustomQuery(property)) {
+                                return null;
+                            }
+                            const newCode = `${caller}.${queryVariant}${queryMethod}(${callArguments
+                                .map((callArgNode) => sourceCode.getText(callArgNode))
+                                .join(', ')}${waitOptionsSourceCode})`;
+                            return fixer.replaceText(node, newCode);
+                        },
+                    });
+                    return;
+                }
+                if (!isSyncQuery(argument)) {
+                    return;
+                }
+                const fullQueryMethod = getWrongQueryName(argument);
+                if (!fullQueryMethod) {
+                    return;
+                }
+                const queryMethod = fullQueryMethod.split('By')[1];
+                const queryVariant = getFindByQueryVariant(fullQueryMethod);
+                const callArguments = getQueryArguments(argument.body);
+                reportInvalidUsage(node, {
+                    queryMethod,
+                    queryVariant,
+                    prevQuery: fullQueryMethod,
+                    waitForMethodName,
+                    fix(fixer) {
+                        if (helpers.isCustomQuery(argument.body
+                            .callee)) {
+                            return null;
+                        }
+                        const findByMethod = `${queryVariant}${queryMethod}`;
+                        const allFixes = [];
+                        const newCode = `${findByMethod}(${callArguments
+                            .map((callArgNode) => sourceCode.getText(callArgNode))
+                            .join(', ')})`;
+                        allFixes.push(fixer.replaceText(node, newCode));
+                        const definition = findRenderDefinitionDeclaration(context.getScope(), fullQueryMethod);
+                        if (!definition) {
+                            return allFixes;
+                        }
+                        if (definition.parent &&
+                            (0, node_utils_1.isObjectPattern)(definition.parent.parent)) {
+                            const allVariableDeclarations = definition.parent.parent;
+                            if (allVariableDeclarations.properties.some((p) => (0, node_utils_1.isProperty)(p) &&
+                                utils_1.ASTUtils.isIdentifier(p.key) &&
+                                p.key.name === findByMethod)) {
+                                return allFixes;
+                            }
+                            const textDestructuring = sourceCode.getText(allVariableDeclarations);
+                            const text = textDestructuring.replace(/(\s*})$/, `, ${findByMethod}$1`);
+                            allFixes.push(fixer.replaceText(allVariableDeclarations, text));
+                        }
+                        return allFixes;
+                    },
+                });
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/prefer-presence-queries.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/prefer-presence-queries.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/prefer-presence-queries.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,78 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'prefer-presence-queries';
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        docs: {
+            description: 'Ensure appropriate `get*`/`query*` queries are used with their respective matchers',
+            recommendedConfig: {
+                dom: 'error',
+                angular: 'error',
+                react: 'error',
+                vue: 'error',
+                marko: 'error',
+            },
+        },
+        messages: {
+            wrongPresenceQuery: 'Use `getBy*` queries rather than `queryBy*` for checking element is present',
+            wrongAbsenceQuery: 'Use `queryBy*` queries rather than `getBy*` for checking element is NOT present',
+        },
+        schema: [
+            {
+                type: 'object',
+                additionalProperties: false,
+                properties: {
+                    presence: {
+                        type: 'boolean',
+                    },
+                    absence: {
+                        type: 'boolean',
+                    },
+                },
+            },
+        ],
+        type: 'suggestion',
+    },
+    defaultOptions: [
+        {
+            presence: true,
+            absence: true,
+        },
+    ],
+    create(context, [{ absence = true, presence = true }], helpers) {
+        return {
+            'CallExpression Identifier'(node) {
+                const expectCallNode = (0, node_utils_1.findClosestCallNode)(node, 'expect');
+                const withinCallNode = (0, node_utils_1.findClosestCallNode)(node, 'within');
+                if (!expectCallNode || !(0, node_utils_1.isMemberExpression)(expectCallNode.parent)) {
+                    return;
+                }
+                if (!helpers.isSyncQuery(node)) {
+                    return;
+                }
+                const isPresenceQuery = helpers.isGetQueryVariant(node);
+                const expectStatement = expectCallNode.parent;
+                const isPresenceAssert = helpers.isPresenceAssert(expectStatement);
+                const isAbsenceAssert = helpers.isAbsenceAssert(expectStatement);
+                if (!isPresenceAssert && !isAbsenceAssert) {
+                    return;
+                }
+                if (presence &&
+                    (withinCallNode || isPresenceAssert) &&
+                    !isPresenceQuery) {
+                    context.report({ node, messageId: 'wrongPresenceQuery' });
+                }
+                else if (!withinCallNode &&
+                    absence &&
+                    isAbsenceAssert &&
+                    isPresenceQuery) {
+                    context.report({ node, messageId: 'wrongAbsenceQuery' });
+                }
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/prefer-query-by-disappearance.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/prefer-query-by-disappearance.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/prefer-query-by-disappearance.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,120 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'prefer-query-by-disappearance';
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'problem',
+        docs: {
+            description: 'Suggest using `queryBy*` queries when waiting for disappearance',
+            recommendedConfig: {
+                dom: 'error',
+                angular: 'error',
+                react: 'error',
+                vue: 'error',
+                marko: 'error',
+            },
+        },
+        messages: {
+            preferQueryByDisappearance: 'Prefer using queryBy* when waiting for disappearance',
+        },
+        schema: [],
+    },
+    defaultOptions: [],
+    create(context, _, helpers) {
+        function isWaitForElementToBeRemoved(node) {
+            const identifierNode = (0, node_utils_1.getPropertyIdentifierNode)(node);
+            if (!identifierNode) {
+                return false;
+            }
+            return helpers.isAsyncUtil(identifierNode, ['waitForElementToBeRemoved']);
+        }
+        function reportExpression(node) {
+            const argumentProperty = (0, node_utils_1.isMemberExpression)(node)
+                ? (0, node_utils_1.getPropertyIdentifierNode)(node.property)
+                : (0, node_utils_1.getPropertyIdentifierNode)(node);
+            if (!argumentProperty) {
+                return false;
+            }
+            if (helpers.isGetQueryVariant(argumentProperty) ||
+                helpers.isFindQueryVariant(argumentProperty)) {
+                context.report({
+                    node: argumentProperty,
+                    messageId: 'preferQueryByDisappearance',
+                });
+                return true;
+            }
+            return false;
+        }
+        function checkNonCallbackViolation(node) {
+            if (!(0, node_utils_1.isCallExpression)(node)) {
+                return false;
+            }
+            if (!(0, node_utils_1.isMemberExpression)(node.callee) &&
+                !(0, node_utils_1.getPropertyIdentifierNode)(node.callee)) {
+                return false;
+            }
+            return reportExpression(node.callee);
+        }
+        function isReturnViolation(node) {
+            if (!(0, node_utils_1.isReturnStatement)(node) || !(0, node_utils_1.isCallExpression)(node.argument)) {
+                return false;
+            }
+            return reportExpression(node.argument.callee);
+        }
+        function isNonReturnViolation(node) {
+            if (!(0, node_utils_1.isExpressionStatement)(node) || !(0, node_utils_1.isCallExpression)(node.expression)) {
+                return false;
+            }
+            if (!(0, node_utils_1.isMemberExpression)(node.expression.callee) &&
+                !(0, node_utils_1.getPropertyIdentifierNode)(node.expression.callee)) {
+                return false;
+            }
+            return reportExpression(node.expression.callee);
+        }
+        function isStatementViolation(statement) {
+            return isReturnViolation(statement) || isNonReturnViolation(statement);
+        }
+        function checkFunctionExpressionViolation(node) {
+            if (!(0, node_utils_1.isFunctionExpression)(node)) {
+                return false;
+            }
+            return node.body.body.some((statement) => isStatementViolation(statement));
+        }
+        function isArrowFunctionBodyViolation(node) {
+            if (!(0, node_utils_1.isArrowFunctionExpression)(node) || !(0, node_utils_1.isBlockStatement)(node.body)) {
+                return false;
+            }
+            return node.body.body.some((statement) => isStatementViolation(statement));
+        }
+        function isArrowFunctionImplicitReturnViolation(node) {
+            if (!(0, node_utils_1.isArrowFunctionExpression)(node) || !(0, node_utils_1.isCallExpression)(node.body)) {
+                return false;
+            }
+            if (!(0, node_utils_1.isMemberExpression)(node.body.callee) &&
+                !(0, node_utils_1.getPropertyIdentifierNode)(node.body.callee)) {
+                return false;
+            }
+            return reportExpression(node.body.callee);
+        }
+        function checkArrowFunctionViolation(node) {
+            return (isArrowFunctionBodyViolation(node) ||
+                isArrowFunctionImplicitReturnViolation(node));
+        }
+        function check(node) {
+            if (!isWaitForElementToBeRemoved(node)) {
+                return;
+            }
+            const argumentNode = node.arguments[0];
+            checkNonCallbackViolation(argumentNode);
+            checkArrowFunctionViolation(argumentNode);
+            checkFunctionExpressionViolation(argumentNode);
+        }
+        return {
+            CallExpression: check,
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/prefer-query-matchers.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/prefer-query-matchers.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/prefer-query-matchers.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,83 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'prefer-query-matchers';
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        docs: {
+            description: 'Ensure the configured `get*`/`query*` query is used with the corresponding matchers',
+            recommendedConfig: {
+                dom: false,
+                angular: false,
+                react: false,
+                vue: false,
+                marko: false,
+            },
+        },
+        messages: {
+            wrongQueryForMatcher: 'Use `{{ query }}By*` queries for {{ matcher }}',
+        },
+        schema: [
+            {
+                type: 'object',
+                additionalProperties: false,
+                properties: {
+                    validEntries: {
+                        type: 'array',
+                        items: {
+                            type: 'object',
+                            properties: {
+                                query: {
+                                    type: 'string',
+                                    enum: ['get', 'query'],
+                                },
+                                matcher: {
+                                    type: 'string',
+                                },
+                            },
+                        },
+                    },
+                },
+            },
+        ],
+        type: 'suggestion',
+    },
+    defaultOptions: [
+        {
+            validEntries: [],
+        },
+    ],
+    create(context, [{ validEntries }], helpers) {
+        return {
+            'CallExpression Identifier'(node) {
+                const expectCallNode = (0, node_utils_1.findClosestCallNode)(node, 'expect');
+                if (!expectCallNode || !(0, node_utils_1.isMemberExpression)(expectCallNode.parent)) {
+                    return;
+                }
+                if (!helpers.isSyncQuery(node)) {
+                    return;
+                }
+                const isGetBy = helpers.isGetQueryVariant(node);
+                const expectStatement = expectCallNode.parent;
+                for (const entry of validEntries) {
+                    const { query, matcher } = entry;
+                    const isMatchingAssertForThisEntry = helpers.isMatchingAssert(expectStatement, matcher);
+                    if (!isMatchingAssertForThisEntry) {
+                        continue;
+                    }
+                    const actualQuery = isGetBy ? 'get' : 'query';
+                    if (query !== actualQuery) {
+                        context.report({
+                            node,
+                            messageId: 'wrongQueryForMatcher',
+                            data: { query, matcher },
+                        });
+                    }
+                }
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/prefer-screen-queries.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/prefer-screen-queries.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/prefer-screen-queries.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,132 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'prefer-screen-queries';
+const ALLOWED_RENDER_PROPERTIES_FOR_DESTRUCTURING = [
+    'container',
+    'baseElement',
+];
+function usesContainerOrBaseElement(node) {
+    const secondArgument = node.arguments[1];
+    return ((0, node_utils_1.isObjectExpression)(secondArgument) &&
+        secondArgument.properties.some((property) => (0, node_utils_1.isProperty)(property) &&
+            utils_1.ASTUtils.isIdentifier(property.key) &&
+            ALLOWED_RENDER_PROPERTIES_FOR_DESTRUCTURING.includes(property.key.name)));
+}
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'suggestion',
+        docs: {
+            description: 'Suggest using `screen` while querying',
+            recommendedConfig: {
+                dom: 'error',
+                angular: 'error',
+                react: 'error',
+                vue: 'error',
+                marko: 'error',
+            },
+        },
+        messages: {
+            preferScreenQueries: 'Avoid destructuring queries from `render` result, use `screen.{{ name }}` instead',
+        },
+        schema: [],
+    },
+    defaultOptions: [],
+    create(context, _, helpers) {
+        const renderWrapperNames = [];
+        function detectRenderWrapper(node) {
+            const innerFunction = (0, node_utils_1.getInnermostReturningFunction)(context, node);
+            if (innerFunction) {
+                renderWrapperNames.push((0, node_utils_1.getFunctionName)(innerFunction));
+            }
+        }
+        function isReportableRender(node) {
+            return (helpers.isRenderUtil(node) || renderWrapperNames.includes(node.name));
+        }
+        function reportInvalidUsage(node) {
+            context.report({
+                node,
+                messageId: 'preferScreenQueries',
+                data: {
+                    name: node.name,
+                },
+            });
+        }
+        function saveSafeDestructuredQueries(node) {
+            if ((0, node_utils_1.isObjectPattern)(node.id)) {
+                for (const property of node.id.properties) {
+                    if ((0, node_utils_1.isProperty)(property) &&
+                        utils_1.ASTUtils.isIdentifier(property.key) &&
+                        helpers.isBuiltInQuery(property.key)) {
+                        safeDestructuredQueries.push(property.key.name);
+                    }
+                }
+            }
+        }
+        function isIdentifierAllowed(name) {
+            return ['screen', ...withinDeclaredVariables].includes(name);
+        }
+        const safeDestructuredQueries = [];
+        const withinDeclaredVariables = [];
+        return {
+            VariableDeclarator(node) {
+                if (!(0, node_utils_1.isCallExpression)(node.init) ||
+                    !utils_1.ASTUtils.isIdentifier(node.init.callee)) {
+                    return;
+                }
+                const isComingFromValidRender = isReportableRender(node.init.callee);
+                if (!isComingFromValidRender) {
+                    saveSafeDestructuredQueries(node);
+                }
+                const isWithinFunction = node.init.callee.name === 'within';
+                const usesRenderOptions = isComingFromValidRender && usesContainerOrBaseElement(node.init);
+                if (!isWithinFunction && !usesRenderOptions) {
+                    return;
+                }
+                if ((0, node_utils_1.isObjectPattern)(node.id)) {
+                    saveSafeDestructuredQueries(node);
+                }
+                else if (utils_1.ASTUtils.isIdentifier(node.id)) {
+                    withinDeclaredVariables.push(node.id.name);
+                }
+            },
+            CallExpression(node) {
+                const identifierNode = (0, node_utils_1.getDeepestIdentifierNode)(node);
+                if (!identifierNode) {
+                    return;
+                }
+                if (helpers.isRenderUtil(identifierNode)) {
+                    detectRenderWrapper(identifierNode);
+                }
+                if (!helpers.isBuiltInQuery(identifierNode)) {
+                    return;
+                }
+                if (!(0, node_utils_1.isMemberExpression)(identifierNode.parent)) {
+                    const isSafeDestructuredQuery = safeDestructuredQueries.some((queryName) => queryName === identifierNode.name);
+                    if (isSafeDestructuredQuery) {
+                        return;
+                    }
+                    reportInvalidUsage(identifierNode);
+                    return;
+                }
+                const memberExpressionNode = identifierNode.parent;
+                if ((0, node_utils_1.isCallExpression)(memberExpressionNode.object) &&
+                    utils_1.ASTUtils.isIdentifier(memberExpressionNode.object.callee) &&
+                    memberExpressionNode.object.callee.name !== 'within' &&
+                    isReportableRender(memberExpressionNode.object.callee) &&
+                    !usesContainerOrBaseElement(memberExpressionNode.object)) {
+                    reportInvalidUsage(identifierNode);
+                    return;
+                }
+                if (utils_1.ASTUtils.isIdentifier(memberExpressionNode.object) &&
+                    !isIdentifierAllowed(memberExpressionNode.object.name)) {
+                    reportInvalidUsage(identifierNode);
+                }
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/prefer-user-event.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/prefer-user-event.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/prefer-user-event.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,147 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.MAPPING_TO_USER_EVENT = exports.UserEventMethods = exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'prefer-user-event';
+exports.UserEventMethods = [
+    'click',
+    'dblClick',
+    'type',
+    'upload',
+    'clear',
+    'selectOptions',
+    'deselectOptions',
+    'tab',
+    'hover',
+    'unhover',
+    'paste',
+];
+exports.MAPPING_TO_USER_EVENT = {
+    click: ['click', 'type', 'selectOptions', 'deselectOptions'],
+    change: ['upload', 'type', 'clear', 'selectOptions', 'deselectOptions'],
+    dblClick: ['dblClick'],
+    input: ['type', 'upload', 'selectOptions', 'deselectOptions', 'paste'],
+    keyDown: ['type', 'tab'],
+    keyPress: ['type'],
+    keyUp: ['type', 'tab'],
+    mouseDown: ['click', 'dblClick', 'selectOptions', 'deselectOptions'],
+    mouseEnter: ['hover', 'selectOptions', 'deselectOptions'],
+    mouseLeave: ['unhover'],
+    mouseMove: ['hover', 'unhover', 'selectOptions', 'deselectOptions'],
+    mouseOut: ['unhover'],
+    mouseOver: ['hover', 'selectOptions', 'deselectOptions'],
+    mouseUp: ['click', 'dblClick', 'selectOptions', 'deselectOptions'],
+    paste: ['paste'],
+    pointerDown: ['click', 'dblClick', 'selectOptions', 'deselectOptions'],
+    pointerEnter: ['hover', 'selectOptions', 'deselectOptions'],
+    pointerLeave: ['unhover'],
+    pointerMove: ['hover', 'unhover', 'selectOptions', 'deselectOptions'],
+    pointerOut: ['unhover'],
+    pointerOver: ['hover', 'selectOptions', 'deselectOptions'],
+    pointerUp: ['click', 'dblClick', 'selectOptions', 'deselectOptions'],
+};
+function buildErrorMessage(fireEventMethod) {
+    const userEventMethods = exports.MAPPING_TO_USER_EVENT[fireEventMethod].map((methodName) => `userEvent.${methodName}`);
+    return userEventMethods.join(', ').replace(/, ([a-zA-Z.]+)$/, ', or $1');
+}
+const fireEventMappedMethods = Object.keys(exports.MAPPING_TO_USER_EVENT);
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'suggestion',
+        docs: {
+            description: 'Suggest using `userEvent` over `fireEvent` for simulating user interactions',
+            recommendedConfig: {
+                dom: false,
+                angular: false,
+                react: false,
+                vue: false,
+                marko: false,
+            },
+        },
+        messages: {
+            preferUserEvent: 'Prefer using {{userEventMethods}} over fireEvent.{{fireEventMethod}}',
+        },
+        schema: [
+            {
+                type: 'object',
+                properties: {
+                    allowedMethods: { type: 'array' },
+                },
+            },
+        ],
+    },
+    defaultOptions: [{ allowedMethods: [] }],
+    create(context, [options], helpers) {
+        const { allowedMethods } = options;
+        const createEventVariables = {};
+        const isfireEventMethodAllowed = (methodName) => !fireEventMappedMethods.includes(methodName) ||
+            allowedMethods.includes(methodName);
+        const getFireEventMethodName = (callExpressionNode, node) => {
+            if (!utils_1.ASTUtils.isIdentifier(callExpressionNode.callee) &&
+                !(0, node_utils_1.isMemberExpression)(callExpressionNode.callee)) {
+                return node.name;
+            }
+            const secondArgument = callExpressionNode.arguments[1];
+            if (utils_1.ASTUtils.isIdentifier(secondArgument) &&
+                createEventVariables[secondArgument.name] !== undefined) {
+                return createEventVariables[secondArgument.name];
+            }
+            if (!(0, node_utils_1.isCallExpression)(secondArgument) ||
+                !helpers.isCreateEventUtil(secondArgument)) {
+                return node.name;
+            }
+            if (utils_1.ASTUtils.isIdentifier(secondArgument.callee)) {
+                return secondArgument.arguments[0]
+                    .value;
+            }
+            return secondArgument.callee
+                .property.name;
+        };
+        return {
+            'CallExpression Identifier'(node) {
+                if (!helpers.isFireEventMethod(node)) {
+                    return;
+                }
+                const closestCallExpression = (0, node_utils_1.findClosestCallExpressionNode)(node, true);
+                if (!closestCallExpression) {
+                    return;
+                }
+                const fireEventMethodName = getFireEventMethodName(closestCallExpression, node);
+                if (!fireEventMethodName ||
+                    isfireEventMethodAllowed(fireEventMethodName)) {
+                    return;
+                }
+                context.report({
+                    node: closestCallExpression.callee,
+                    messageId: 'preferUserEvent',
+                    data: {
+                        userEventMethods: buildErrorMessage(fireEventMethodName),
+                        fireEventMethod: fireEventMethodName,
+                    },
+                });
+            },
+            VariableDeclarator(node) {
+                if (!(0, node_utils_1.isCallExpression)(node.init) ||
+                    !helpers.isCreateEventUtil(node.init) ||
+                    !utils_1.ASTUtils.isIdentifier(node.id)) {
+                    return;
+                }
+                let fireEventMethodName = '';
+                if ((0, node_utils_1.isMemberExpression)(node.init.callee) &&
+                    utils_1.ASTUtils.isIdentifier(node.init.callee.property)) {
+                    fireEventMethodName = node.init.callee.property.name;
+                }
+                else if (node.init.arguments.length > 0) {
+                    fireEventMethodName = node.init.arguments[0]
+                        .value;
+                }
+                if (!isfireEventMethodAllowed(fireEventMethodName)) {
+                    createEventVariables[node.id.name] = fireEventMethodName;
+                }
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/prefer-wait-for.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/prefer-wait-for.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/prefer-wait-for.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,146 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'prefer-wait-for';
+const DEPRECATED_METHODS = ['wait', 'waitForElement', 'waitForDomChange'];
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'suggestion',
+        docs: {
+            description: 'Use `waitFor` instead of deprecated wait methods',
+            recommendedConfig: {
+                dom: false,
+                angular: false,
+                react: false,
+                vue: false,
+                marko: false,
+            },
+        },
+        messages: {
+            preferWaitForMethod: '`{{ methodName }}` is deprecated in favour of `waitFor`',
+            preferWaitForImport: 'import `waitFor` instead of deprecated async utils',
+            preferWaitForRequire: 'require `waitFor` instead of deprecated async utils',
+        },
+        fixable: 'code',
+        schema: [],
+    },
+    defaultOptions: [],
+    create(context, _, helpers) {
+        let addWaitFor = false;
+        const reportRequire = (node) => {
+            context.report({
+                node,
+                messageId: 'preferWaitForRequire',
+                fix(fixer) {
+                    const excludedImports = [...DEPRECATED_METHODS, 'waitFor'];
+                    const newAllRequired = node.properties
+                        .filter((s) => (0, node_utils_1.isProperty)(s) &&
+                        utils_1.ASTUtils.isIdentifier(s.key) &&
+                        !excludedImports.includes(s.key.name))
+                        .map((s) => s.key.name);
+                    newAllRequired.push('waitFor');
+                    return fixer.replaceText(node, `{ ${newAllRequired.join(',')} }`);
+                },
+            });
+        };
+        const reportImport = (node) => {
+            context.report({
+                node,
+                messageId: 'preferWaitForImport',
+                fix(fixer) {
+                    const excludedImports = [...DEPRECATED_METHODS, 'waitFor'];
+                    const newImports = node.specifiers
+                        .map((specifier) => (0, node_utils_1.isImportSpecifier)(specifier) &&
+                        !excludedImports.includes(specifier.imported.name) &&
+                        specifier.imported.name)
+                        .filter(Boolean);
+                    newImports.push('waitFor');
+                    const newNode = `import { ${newImports.join(',')} } from '${node.source.value}';`;
+                    return fixer.replaceText(node, newNode);
+                },
+            });
+        };
+        const reportWait = (node) => {
+            context.report({
+                node,
+                messageId: 'preferWaitForMethod',
+                data: {
+                    methodName: node.name,
+                },
+                fix(fixer) {
+                    const callExpressionNode = (0, node_utils_1.findClosestCallExpressionNode)(node);
+                    if (!callExpressionNode) {
+                        return null;
+                    }
+                    const [arg] = callExpressionNode.arguments;
+                    const fixers = [];
+                    if (arg) {
+                        fixers.push(fixer.replaceText(node, 'waitFor'));
+                        if (node.name === 'waitForDomChange') {
+                            fixers.push(fixer.insertTextBefore(arg, '() => {}, '));
+                        }
+                    }
+                    else {
+                        let methodReplacement = 'waitFor(() => {})';
+                        if ((0, node_utils_1.isMemberExpression)(node.parent) &&
+                            utils_1.ASTUtils.isIdentifier(node.parent.object)) {
+                            methodReplacement = `${node.parent.object.name}.${methodReplacement}`;
+                        }
+                        const newText = methodReplacement;
+                        fixers.push(fixer.replaceText(callExpressionNode, newText));
+                    }
+                    return fixers;
+                },
+            });
+        };
+        return {
+            'CallExpression > MemberExpression'(node) {
+                const isDeprecatedMethod = utils_1.ASTUtils.isIdentifier(node.property) &&
+                    DEPRECATED_METHODS.includes(node.property.name);
+                if (!isDeprecatedMethod) {
+                    return;
+                }
+                if (!helpers.isNodeComingFromTestingLibrary(node)) {
+                    return;
+                }
+                addWaitFor = true;
+                reportWait(node.property);
+            },
+            'CallExpression > Identifier'(node) {
+                if (!DEPRECATED_METHODS.includes(node.name)) {
+                    return;
+                }
+                if (!helpers.isNodeComingFromTestingLibrary(node)) {
+                    return;
+                }
+                addWaitFor = true;
+                reportWait(node);
+            },
+            'Program:exit'() {
+                var _a;
+                if (!addWaitFor) {
+                    return;
+                }
+                const testingLibraryNode = (_a = helpers.getCustomModuleImportNode()) !== null && _a !== void 0 ? _a : helpers.getTestingLibraryImportNode();
+                if ((0, node_utils_1.isCallExpression)(testingLibraryNode)) {
+                    const parent = testingLibraryNode.parent;
+                    if (!(0, node_utils_1.isObjectPattern)(parent.id)) {
+                        return;
+                    }
+                    reportRequire(parent.id);
+                }
+                else if (testingLibraryNode) {
+                    if (testingLibraryNode.specifiers.length === 1 &&
+                        (0, node_utils_1.isImportNamespaceSpecifier)(testingLibraryNode.specifiers[0])) {
+                        return;
+                    }
+                    reportImport(testingLibraryNode);
+                }
+            },
+        };
+    },
+});
Index: frontend/node_modules/eslint-plugin-testing-library/rules/render-result-naming-convention.js
===================================================================
--- frontend/node_modules/eslint-plugin-testing-library/rules/render-result-naming-convention.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-testing-library/rules/render-result-naming-convention.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,83 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.RULE_NAME = void 0;
+const utils_1 = require("@typescript-eslint/utils");
+const create_testing_library_rule_1 = require("../create-testing-library-rule");
+const node_utils_1 = require("../node-utils");
+exports.RULE_NAME = 'render-result-naming-convention';
+const ALLOWED_VAR_NAMES = ['view', 'utils'];
+const ALLOWED_VAR_NAMES_TEXT = ALLOWED_VAR_NAMES.map((name) => `\`${name}\``)
+    .join(', ')
+    .replace(/, ([^,]*)$/, ', or $1');
+exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
+    name: exports.RULE_NAME,
+    meta: {
+        type: 'suggestion',
+        docs: {
+            description: 'Enforce a valid naming for return value from `render`',
+            recommendedConfig: {
+                dom: false,
+                angular: 'error',
+                react: 'error',
+                vue: 'error',
+                marko: 'error',
+            },
+        },
+        messages: {
+            renderResultNamingConvention: `\`{{ renderResultName }}\` is not a recommended name for \`render\` returned value. Instead, you should destructure it, or name it using one of: ${ALLOWED_VAR_NAMES_TEXT}`,
+        },
+        schema: [],
+    },
+    defaultOptions: [],
+    create(context, _, helpers) {
+        const renderWrapperNames = [];
+        function detectRenderWrapper(node) {
+            const innerFunction = (0, node_utils_1.getInnermostReturningFunction)(context, node);
+            if (innerFunction) {
+                renderWrapperNames.push((0, node_utils_1.getFunctionName)(innerFunction));
+            }
+        }
+        return {
+            CallExpression(node) {
+                const callExpressionIdentifier = (0, node_utils_1.getDeepestIdentifierNode)(node);
+                if (!callExpressionIdentifier) {
+                    return;
+                }
+                if (helpers.isRenderUtil(callExpressionIdentifier)) {
+                    detectRenderWrapper(callExpressionIdentifier);
+                }
+            },
+            VariableDeclarator(node) {
+                if (!node.init) {
+                    return;
+                }
+                const initIdentifierNode = (0, node_utils_1.getDeepestIdentifierNode)(node.init);
+                if (!initIdentifierNode) {
+                    return;
+                }
+                if (!helpers.isRenderVariableDeclarator(node) &&
+                    !renderWrapperNames.includes(initIdentifierNode.name)) {
+                    return;
+                }
+                if ((0, node_utils_1.isObjectPattern)(node.id)) {
+                    return;
+                }
+                const renderResultName = utils_1.ASTUtils.isIdentifier(node.id) && node.id.name;
+                if (!renderResultName) {
+                    return;
+                }
+                const isAllowedRenderResultName = ALLOWED_VAR_NAMES.includes(renderResultName);
+                if (isAllowedRenderResultName) {
+                    return;
+                }
+                context.report({
+                    node,
+                    messageId: 'renderResultNamingConvention',
+                    data: {
+                        renderResultName,
+                    },
+                });
+            },
+        };
+    },
+});
