diff --git a/.drone.star b/.drone.star index 199c10696f2..fe2d95a70fc 100644 --- a/.drone.star +++ b/.drone.star @@ -1066,7 +1066,7 @@ def unitTests(ctx): return [{ "kind": "pipeline", "type": "docker", - "name": "unit-and-integration-tests", + "name": "unit-tests", "workspace": { "base": dir["base"], "path": config["app"], @@ -1101,13 +1101,6 @@ def unitTests(ctx): "yarn test:unit", ], }, - { - "name": "integration-tests", - "image": OC_CI_NODEJS, - "commands": [ - "yarn test:integration", - ], - }, { "name": "sonarcloud", "image": SONARSOURCE_SONAR_SCANNER_CLI, @@ -3078,7 +3071,6 @@ def skipIfUnchanged(ctx, type): "^__fixtures__/.*", "^__mocks__/.*", "^packages/.*/tests/.*", - "^tests/integration/.*", "^tests/e2e/.*", "^tests/unit/.*", ] @@ -3093,7 +3085,6 @@ def skipIfUnchanged(ctx, type): "^__mocks__/.*", "^packages/.*/tests/.*", "^tests/acceptance/.*", - "^tests/integration/.*", "^tests/unit/.*", ] skip_step["settings"] = { diff --git a/changelog/unreleased/enhancement-remove-integration-tests b/changelog/unreleased/enhancement-remove-integration-tests new file mode 100644 index 00000000000..7f56ed7e07b --- /dev/null +++ b/changelog/unreleased/enhancement-remove-integration-tests @@ -0,0 +1,6 @@ +Enhancement: Get rid of the integration tests + +We've decided to get rid of our integration test suite. +Our unit and e2e tests get better and better with each release and have now reached the point where they can replace the integration tests. + +https://github.com/owncloud/web/pull/6863 diff --git a/docs/development.md b/docs/development.md index 9a4462a08ed..edf67f84c9a 100644 --- a/docs/development.md +++ b/docs/development.md @@ -18,7 +18,7 @@ Everyone is invited to contribute. Simply fork [the codebase](), check [the issu ### Linting and tests -To make sure your pull request can be efficiently reviewed and won't need a lot of changes down the road, please run the linter and the unit&integration tests via `yarn lint --fix` and `yarn test:unit && yarn test:integration` locally. [Our CI](https://drone.owncloud.com/owncloud/web) will run on pull requests and report back any problems after that. For a further introduction on how we handle testing, please head to the [testing docs]({{< ref "testing/_index.md" >}}). +To make sure your pull request can be efficiently reviewed and won't need a lot of changes down the road, please run the linter and the unit tests via `yarn lint --fix` and `yarn test:unit` locally. [Our CI](https://drone.owncloud.com/owncloud/web) will run on pull requests and report back any problems after that. For a further introduction on how we handle testing, please head to the [testing docs]({{< ref "testing/_index.md" >}}). ### Changelog items diff --git a/docs/testing/testing.md b/docs/testing/testing.md index f76c812f988..443fa556de0 100644 --- a/docs/testing/testing.md +++ b/docs/testing/testing.md @@ -21,13 +21,12 @@ $ cd web $ yarn ``` -### Unit & Integration Tests +### Unit Tests -We have a steadily growing coverage of both unit and integration tests. You can run them locally via +We have a steadily growing coverage of unit tests. You can run them locally via ```shell $ yarn test:unit -$ yarn test:integration ``` You can also specify which tests to run by giving a path param, like so: `yarn test:unit packages//tests/unit/path/to/test.spec.js`. diff --git a/package.json b/package.json index f41c4bf574a..b0df70eddc2 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,6 @@ "depcheck": "depcheck", "lint": "eslint '{packages,tests}/**/*.{js,ts,vue}' --color", "serve": "SERVER=true yarn build:w", - "test:integration": "jest --config ./tests/integration/config/jest.config.js", "test:e2e:cucumber": "NODE_TLS_REJECT_UNAUTHORIZED=0 cucumber-js --profile=e2e -f json:tests/e2e/cucumber/report/cucumber_report.json", "test:unit": "NODE_OPTIONS=--unhandled-rejections=throw jest --coverage --config ./tests/unit/config/jest.config.js", "licenses:check": "license-checker-rseidelsohn --summary --relativeLicensePath --onlyAllow 'Python-2.0;Apache*;Apache License, Version 2.0;Apache-2.0;Apache 2.0;Artistic-2.0;BSD;BSD-3-Clause;CC-BY-3.0;CC-BY-4.0;CC0-1.0;ISC;MIT;MPL-2.0;Public Domain;Unicode-TOU;Unlicense;WTFPL' --excludePackages 'draw-io;external;files;text-editor;preview;owncloud-design-system;pdf-viewer;search;user-management;web-client;web-pkg;web-runtime'", @@ -60,10 +59,6 @@ "@rollup/plugin-inject": "^4.0.4", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-typescript": "^8.3.0", - "@testing-library/dom": "^8.11.0", - "@testing-library/jest-dom": "^5.16.1", - "@testing-library/user-event": "^13.5.0", - "@testing-library/vue": "^5.8.2", "@types/jest": "^27.4.1", "@types/jest-axe": "^3.5.3", "@types/lodash-es": "^4.17.5", @@ -136,7 +131,8 @@ "url-search-params-polyfill": "^8.0.0", "vue-jest": "^3.0.7", "vue-template-compiler": "^2.6.12", - "vuex-mock-store": "0.0.8" + "vuex-mock-store": "0.0.8", + "wait-for-expect": "^3.0.2" }, "engines": { "node": ">=14 <=16" diff --git a/packages/web-app-files/tests/integration/helpers/date.js b/packages/web-app-files/tests/integration/helpers/date.js deleted file mode 100644 index 2293c700180..00000000000 --- a/packages/web-app-files/tests/integration/helpers/date.js +++ /dev/null @@ -1,52 +0,0 @@ -import userEvent from '@testing-library/user-event' - -/** - * Adds a given number of days to the current date - * @param {number} days number of days to be added to the current date - * @returns date in the future with added days - */ -export function getDateInFuture(days) { - const date = new Date() - - date.setDate(new Date().getDate() + days) - - return date -} - -export async function navigateToDate(date, component, direction = 'right') { - const formatDate = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' } - - if (['right', 'left'].indexOf(direction) < 0) { - return Promise.reject(new Error('invalid value for direction. Please use "left" or "right"')) - } - const { queryByText, baseElement, findByText } = component - - while (true) { - const dateHeader = await queryByText( - date.toLocaleString('en', { month: 'long', year: 'numeric' }) - ) - - if (!dateHeader) { - const nextMonthBtn = baseElement.querySelector(`.vc-arrow.is-${direction}`) - await userEvent.click(nextMonthBtn) - } else { - break - } - } - - const dateSelector = document.evaluate( - `//span[contains(@class, "vc-day-content vc-focusable") and @tabindex="-1" and @aria-label="${date.toLocaleDateString( - 'en', - formatDate - )}" and text()="${date.getDate()}"]`, - baseElement, - null, - XPathResult.FIRST_ORDERED_NODE_TYPE, - null - ).singleNodeValue - - expect( - await findByText(date.toLocaleString('en', { month: 'long', year: 'numeric' })) - ).toBeVisible() - await userEvent.click(dateSelector) -} diff --git a/packages/web-app-files/tests/integration/specs/linkExpirationDate.spec.js b/packages/web-app-files/tests/integration/specs/linkExpirationDate.spec.js deleted file mode 100644 index 3804e7e133d..00000000000 --- a/packages/web-app-files/tests/integration/specs/linkExpirationDate.spec.js +++ /dev/null @@ -1,280 +0,0 @@ -import '@testing-library/jest-dom' -import { render, fireEvent, waitFor, within } from '@testing-library/vue' -import merge from 'lodash-es/merge' -import StoreFiles from '@files/src/store' -import Store from '@runtime/src/store' -import App from '@files/src/App.vue' -import Favorites from '@files/src/views/Favorites.vue' -import FilesDrop from '@files/src/views/FilesDrop.vue' -import LocationPicker from '@files/src/views/LocationPicker.vue' -import PrivateLink from '@files/src/views/PrivateLink.vue' -import PublicFiles from '@files/src/views/PublicFiles.vue' -import PublicLink from '@files/src/views/PublicLink.vue' -import Personal from '@files/src/views/Personal.vue' -import SharedWithMe from '@files/src/views/shares/SharedWithMe.vue' -import SharedWithOthers from '@files/src/views/shares/SharedWithOthers.vue' -import SharedViaLink from '@files/src/views/shares/SharedViaLink.vue' -import SpaceProject from '@files/src/views/spaces/Project.vue' -import SpaceProjects from '@files/src/views/spaces/Projects.vue' -import Trashbin from '@files/src/views/Trashbin.vue' -import { buildRoutes, createLocationSpaces } from '@files/src/router' -import fileSideBars from '@files/src/fileSideBars' -import { getDateInFuture, navigateToDate } from '../helpers/date' -// eslint-disable-next-line jest/no-mocks-import -import sdkMock from '@/__mocks__/sdk' -import { DateTime } from 'luxon' -import FileLinks from '@files/src/components/SideBar/Shares/FileLinks.vue' - -const routes = buildRoutes({ - App, - Favorites, - Personal, - FilesDrop, - LocationPicker, - PrivateLink, - PublicFiles, - PublicLink, - SharedViaLink, - SharedWithMe, - SharedWithOthers, - Spaces: { - Project: SpaceProject, - Projects: SpaceProjects - }, - Trashbin -}) - -const existingShares = [ - { - shareInfo: { - id: 1, - share_type: 3, - uid_owner: 'alice', - displayname_owner: 'alice', - permissions: '1', - stime: new Date().getTime(), - expiration: DateTime.fromJSDate(getDateInFuture(2)).toFormat('yyyy-MM-dd HH:mm:ss'), - uid_file_owner: 'alice', - displayname_file_owner: 'alice', - path: '/Documents', - item_type: 'folder', - item_source: 10, - file_source: 10, - file_parent: 6, - file_target: '/Documents', - share_with: 'bob', - share_with_displayname: 'bob', - token: 'token', - url: 'url', - name: 'Public link' - } - } -] - -describe('Users can set expiration date when sharing via public link', () => { - afterEach(() => { - jest.resetModules() - jest.restoreAllMocks() - window.sessionStorage.clear() - }) - test('user can set a new expiration date', async () => { - const component = renderComponent() - const { findByTestId, baseElement, getByTestId, queryByTestId } = component - const addBtn = await findByTestId('files-link-add-btn') - - expect(addBtn).toBeVisible() - await fireEvent.click(addBtn) - expect(await findByTestId('new-files-link')).toBeVisible() - await fireEvent.update(baseElement.querySelector('#oc-files-file-link-name'), 'Public link') - - expect(getByTestId('recipient-datepicker')).toBeVisible() - await fireEvent.click(getByTestId('recipient-datepicker-btn')) - - const newDate = getDateInFuture(2) - await navigateToDate(newDate, component) - - const shareBtn = getByTestId('new-files-link-btn') - expect(shareBtn).toBeVisible() - await fireEvent.click(shareBtn) - await waitFor(() => { - return expect(queryByTestId('files-link-being-created')).toBe(null) - }) - - const link = await findByTestId('files-link-id-1') - expect(link).toBeVisible() - - expect( - within(getByTestId('files-link-id-1')).getByLabelText('Expires in in 2 days', { - exact: false - }) - ).toBeVisible() - }) - - test('user can edit an existing expiration date', async () => { - const component = renderComponent({ - mocks: { - $client: { - ...sdkMock, - shares: { - ...sdkMock.shares, - getShares: jest.fn().mockImplementation(() => Promise.resolve(existingShares)) - } - } - } - }) - const { findByTestId, getByTestId } = component - - const link = await findByTestId('files-link-id-1') - expect(link).toBeVisible() - - const editBtn = getByTestId('files-link-id-1-btn-edit') - expect(editBtn).toBeVisible() - await fireEvent.click(editBtn) - - const editExpiryDateBtn = getByTestId('files-link-id-1-edit-edit-expiration') - expect(editExpiryDateBtn).toBeVisible() - await fireEvent.click(editExpiryDateBtn) - - const newDate = getDateInFuture(4) - await navigateToDate(newDate, component) - - expect( - within(getByTestId('files-link-id-1')).getByLabelText('Expires in in 4 days', { - exact: false - }) - ).toBeVisible() - }) - - test('user can remove an existing expiration date', async () => { - const component = renderComponent({ - mocks: { - $client: { - ...sdkMock, - shares: { - ...sdkMock.shares, - getShares: jest.fn().mockImplementation(() => Promise.resolve(existingShares)) - } - } - } - }) - const { findByTestId, getByTestId, queryByTestId } = component - - const link = await findByTestId('files-link-id-1') - expect(link).toBeVisible() - - const editBtn = getByTestId('files-link-id-1-btn-edit') - expect(editBtn).toBeVisible() - await fireEvent.click(editBtn) - - const removeExpiryDateBtn = getByTestId('files-link-id-1-edit-remove-expiration') - expect(removeExpiryDateBtn).toBeVisible() - await fireEvent.click(removeExpiryDateBtn) - await waitFor(() => { - return expect(queryByTestId('files-link-id-1-edit-remove-expiration')).toBe(null) - }) - - expect(within(link).queryByTestId('files-link-id-1-expiration-date')).toBe(null) - }) -}) - -const getTestFolder = () => ({ - type: 'folder', - isFolder: true, - ownerId: 'alice', - ownerDisplayName: 'alice', - mdate: 'Wed, 21 Oct 2015 07:28:00 GMT', - size: '740', - isMounted: jest.fn(() => true), - name: 'lorem.txt', - privateLink: 'some-link', - canShare: jest.fn(() => true), - path: '/documents' -}) - -function createStore(store) { - return merge( - {}, - Store, - { - modules: { - config: { - getters: { - configuration: () => ({ - server: 'https://example.com', - options: {} - }) - } - }, - user: { - state: { - id: 'alice', - capabilities: { - files: { - privateLinks: true - }, - files_sharing: { - public: { - enabled: true, - expire_date: { - enabled: false, - enforced: false - }, - password: { - enforced_for: { - read_only: '0', - upload_only: '0', - read_write: '0' - } - } - } - } - } - } - }, - apps: { - ...Store.modules.apps, - state: { - ...Store.modules.apps.state, - fileSideBars - } - }, - Files: { - ...StoreFiles, - getters: { - ...StoreFiles.getters, - highlightedFile: () => getTestFolder(), - currentFileOutgoingSharesLoading: () => false, - sharesTreeLoading: () => false - }, - actions: { - ...StoreFiles.actions, - loadSharesTree: jest.fn - } - } - } - }, - store - ) -} - -function renderComponent({ store, mocks } = {}) { - return render( - FileLinks, - { - store: createStore(store), - stubs: { - 'avatar-image': true - }, - provide: { - displayedItem: { - value: getTestFolder() - } - }, - routes, - mocks - }, - (vue, store, router) => { - router.push(createLocationSpaces()) - } - ) -} diff --git a/packages/web-app-files/tests/integration/specs/pagination.spec.js b/packages/web-app-files/tests/integration/specs/pagination.spec.js deleted file mode 100644 index b47e77bd875..00000000000 --- a/packages/web-app-files/tests/integration/specs/pagination.spec.js +++ /dev/null @@ -1,131 +0,0 @@ -import '@testing-library/jest-dom' -import { render, waitFor, fireEvent } from '@testing-library/vue' -import merge from 'lodash-es/merge' - -import toKebabCase from '../../../../../tests/helpers/toKebabCase' - -import StoreFiles from '@files/src/store' -import Store from '@runtime/src/store' - -import Personal from '@files/src/views/Personal.vue' -import Favorites from '@files/src/views/Favorites.vue' -import LocationPicker from '@files/src/views/LocationPicker.vue' -import PublicFiles from '@files/src/views/PublicFiles.vue' -import SharedViaLink from '@files/src/views/shares/SharedViaLink.vue' -import SharedWithOthers from '@files/src/views/shares/SharedWithOthers.vue' -import Trashbin from '@files/src/views/Trashbin.vue' -import FilesApp from '@files/src' - -let store -const routes = FilesApp.routes -const stubs = { 'app-bar': true, 'context-actions': true } -const cases = [ - ['Personal', '/spaces/personal/home', Personal], - ['Favorites', '/list/favorites/', Favorites], - ['LocationPicker', '/ops/location-picker/private/move/%2F?resource=%2FDocuments', LocationPicker], - ['PublicFiles', '/public/list/link', PublicFiles], - ['SharedViaLink', '/list/shared-via-link/', SharedViaLink], - ['SharedWithOthers', '/list/shared-with-others/', SharedWithOthers], - ['Trashbin', '/trash/personal', Trashbin] -] - -describe('User can navigate in files list using pagination', () => { - beforeEach(() => { - window.localStorage.setItem('oc_options_items-per-page', '2') - store = merge({}, Store, { - modules: { - config: { - getters: { - configuration: () => ({ - options: { - disablePreviews: true - } - }) - } - }, - user: { - state: { - id: 'admin' - } - }, - Files: StoreFiles - } - }) - }) - - test.each(cases)( - 'Resources get updated when user navigates to a new page via pagination in %s files list', - // eslint-disable-next-line jest/no-done-callback - async (name, route, component) => { - const { getByText, queryByText } = render( - component, - { routes, store, stubs }, - (vue, store, router) => { - vue.directive('translate', jest.fn()) - router.push(route) - } - ) - - await waitFor(() => - expect(document.querySelector(`#files-${toKebabCase(name)}-table`)).toBeVisible() - ) - - expect(getByText('Documents')).toBeVisible() - expect(queryByText('Photos')).toBe(null) - expect(queryByText('ownCloud Manual')).toBe(null) - expect(document.querySelector('.oc-pagination')).toBeVisible() - - // 2 links, 1 current page and 1 next page link - expect(document.querySelectorAll('.oc-pagination-list-item').length).toBe(3) - - const secondPage = document - .evaluate( - "//a[contains(@class, 'oc-pagination-list-item-link') and contains(., '2')]", - document, - null, - XPathResult.ANY_TYPE, - null - ) - .iterateNext() - - expect(secondPage).toBeVisible() - - await fireEvent.click(secondPage) - await waitFor(() => expect(getByText('Photos')).toBeVisible()) - - expect(document.querySelector('.oc-pagination-list-item-current').textContent).toMatch('2') - } - ) - - test.each(cases)( - 'Resources get updated when user navigates to %s directly via URL', - async (name, route, component) => { - // eslint-disable-next-line jest/no-done-callback - const { getByText, queryByText } = render( - component, - { routes, store, stubs }, - (vue, store, router) => { - vue.directive('translate', jest.fn()) - - if (name === 'LocationPicker') { - router.push(`${route}&page=2`) - return - } - - router.push(`${route}?page=2`) - } - ) - - await waitFor(() => - expect(document.querySelector(`#files-${toKebabCase(name)}-table`)).toBeVisible() - ) - - expect(queryByText('Documents')).toBe(null) - expect(getByText('Photos')).toBeVisible() - expect(queryByText('ownCloud Manual')).toBeVisible() - expect(document.querySelector('.oc-pagination')).toBeVisible() - expect(document.querySelectorAll('.oc-pagination-list-item').length).toBe(3) - expect(document.querySelector('.oc-pagination-list-item-current').textContent).toMatch('2') - } - ) -}) diff --git a/packages/web-app-files/tests/integration/specs/peopleExpirationDate.spec.js b/packages/web-app-files/tests/integration/specs/peopleExpirationDate.spec.js deleted file mode 100644 index 1ca8a873864..00000000000 --- a/packages/web-app-files/tests/integration/specs/peopleExpirationDate.spec.js +++ /dev/null @@ -1,483 +0,0 @@ -import '@testing-library/jest-dom' -import { render, fireEvent, waitFor, within } from '@testing-library/vue' -import userEvent from '@testing-library/user-event' -import merge from 'lodash-es/merge' -import App from '@files/src/App.vue' -import StoreFiles from '@files/src/store' -import Store from '@runtime/src/store' -import Favorites from '@files/src/views/Favorites.vue' -import FilesDrop from '@files/src/views/FilesDrop.vue' -import LocationPicker from '@files/src/views/LocationPicker.vue' -import PrivateLink from '@files/src/views/PrivateLink.vue' -import PublicFiles from '@files/src/views/PublicFiles.vue' -import PublicLink from '@files/src/views/PublicLink.vue' -import Personal from '@files/src/views/Personal.vue' -import SharedWithMe from '@files/src/views/shares/SharedWithMe.vue' -import SharedWithOthers from '@files/src/views/shares/SharedWithOthers.vue' -import SharedViaLink from '@files/src/views/shares/SharedViaLink.vue' -import SpaceProject from '@files/src/views/spaces/Project.vue' -import SpaceProjects from '@files/src/views/spaces/Projects.vue' -import Trashbin from '@files/src/views/Trashbin.vue' -import { buildRoutes, createLocationSpaces } from '../../../src/router' - -// eslint-disable-next-line jest/no-mocks-import -// import sdkMock from '@/__mocks__/sdk' - -import FileShares from '@files/src/components/SideBar/Shares/FileShares.vue' -const routes = buildRoutes({ - App, - Favorites, - Personal, - FilesDrop, - LocationPicker, - PrivateLink, - PublicFiles, - PublicLink, - SharedViaLink, - SharedWithMe, - SharedWithOthers, - Spaces: { - Project: SpaceProject, - Projects: SpaceProjects - }, - Trashbin -}) - -// const existingShares = [ -// { -// shareInfo: { -// id: '1', -// share_type: 0, -// uid_owner: 'alice', -// displayname_owner: 'alice', -// permissions: 16, -// stime: new Date().getTime(), -// expiration: getDateInFuture(2).toISOString(), -// uid_file_owner: 'alice', -// displayname_file_owner: 'alice', -// path: '/Documents', -// item_type: 'folder', -// item_source: 10, -// file_source: 10, -// file_parent: 6, -// file_target: '/Documents', -// share_with: 'bob', -// share_with_displayname: 'bob' -// } -// } -// ] - -// const existingSharesWithoutExpiration = [ -// { -// shareInfo: { -// ...existingShares[0].shareInfo, -// expiration: null -// } -// } -// ] - -const selectors = { - inviteForm: { - container: 'new-collaborators-form', - createBtn: 'new-collaborators-form-create-button', - input: '#files-share-invite-input' - }, - autocomplete: { - list: '#vs1__listbox', - itemPrefix: 'recipient-autocomplete-item-' - }, - selectedRecipient: { - containerPrefix: 'recipient-container-' - }, - listItem: { - containerPrefix: 'collaborator-user-item-', - expiration: 'recipient-info-expiration-date', - editBtn: 'collaborator-edit', - removeExpirationBtn: 'collaborator-remove-expiration-btn' - }, - datepicker: { - container: 'recipient-datepicker', - triggerBtn: 'recipient-datepicker-btn' - } -} - -describe('Users can set expiration date when sharing with users or groups', () => { - afterEach(() => { - jest.resetModules() - jest.restoreAllMocks() - window.sessionStorage.clear() - }) - describe('new shares', () => { - test('user can select an expiration date', async () => { - expect(true).toBeTruthy() - // const user = 'bob' - // const days = 2 - // const component = renderComponent() - // - // await searchUser(user, component) - // await selectUser(user, component) - // await triggerDatePicker(component) - // const newDate = getDateInFuture(days) - // await navigateToDate(newDate, component) - // await validateInviteExpiration(days, component) - // await submitInvite(component) - // await validateExpiration(user, days, component) - }) - // test('default expiration gets applied', async () => { - // const user = 'bob' - // const enforcedDays = 4 - // const component = renderComponent({ - // store: { - // modules: { - // user: { - // state: { - // capabilities: { - // files_sharing: { - // user: { - // expire_date: { - // enabled: true, - // enforced: false, - // days: enforcedDays.toString() - // } - // } - // } - // } - // } - // } - // } - // } - // }) - // await searchUser(user, component) - // await selectUser(user, component) - // await validateInviteExpiration(enforcedDays, component) - // await submitInvite(component) - // await validateExpiration(user, enforcedDays, component) - // }) - // test('user can select expiration date within enforced maximum date', async () => { - // const user = 'bob' - // const days = 2 - // const component = renderComponent({ - // store: { - // modules: { - // user: { - // state: { - // capabilities: { - // files_sharing: { - // user: { - // expire_date: { - // enabled: true, - // enforced: true, - // days: '4' - // } - // } - // } - // } - // } - // } - // } - // } - // }) - // await searchUser(user, component) - // await selectUser(user, component) - // await triggerDatePicker(component) - // const newDate = getDateInFuture(days) - // await navigateToDate(newDate, component, 'left') // Since the calendar defaults to the enforced date we need to move left - // await submitInvite(component) - // await validateExpiration(user, days, component) - // }) - }) - - // describe('existing shares', () => { - // test.each([ - // [ - // 'without', - // { - // shares: existingSharesWithoutExpiration - // } - // ], - // [ - // 'with', - // { - // shares: existingShares - // } - // ] - // ])( - // 'user can select an expiration date on a share %s pre-existing expiration', - // async (name, { shares }) => { - // const user = 'bob' - // const days = 4 - // const component = renderComponent({ - // mocks: { - // $client: { - // ...sdkMock, - // shares: { - // ...sdkMock.shares, - // getShares: jest.fn().mockImplementation(() => Promise.resolve(shares)) - // } - // } - // } - // }) - - // await validateExpiration(user, 2, component) - // await showEditDropdown(user, component) - // await triggerDatePicker(component) - // const newDate = getDateInFuture(days) - // await navigateToDate(newDate, component) - // await validateExpiration(user, days, component) - // } - // ) - - // // test('user can remove a pre-existing expiration date', async () => { - // // const user = 'bob' - // // const component = renderComponent({ - // // mocks: { - // // $client: { - // // ...sdkMock, - // // shares: { - // // ...sdkMock.shares, - // // getShares: jest.fn().mockImplementation(() => Promise.resolve(existingShares)) - // // } - // // } - // // } - // // }) - - // // await validateExpiration(user, 2, component) - // // await showEditDropdown(user, component) - // // await removeExpiration(user, component) - // // const listItem = await getListItem(user, component) - // // expect(within(listItem).getByTestId(selectors.listItem.expiration)).toBe(null) - // // }) - - // // test('user can edit expiration date within enforced maximum date', async () => { - // // const user = 'bob' - // // const days = 4 - // // const component = renderComponent({ - // // store: { - // // modules: { - // // user: { - // // state: { - // // capabilities: { - // // files_sharing: { - // // user: { - // // expire_date: { - // // enabled: true, - // // enforced: true, - // // days: '6' - // // } - // // } - // // } - // // } - // // } - // // } - // // } - // // }, - // // mocks: { - // // $client: { - // // ...sdkMock, - // // shares: { - // // ...sdkMock.shares, - // // getShares: jest.fn().mockImplementation(() => Promise.resolve(existingShares)) - // // } - // // } - // // } - // // }) - - // // await validateExpiration(user, 2, component) - // // await showEditDropdown(user, component) - // // await triggerDatePicker(component) - // // const newDate = getDateInFuture(days) - // // await navigateToDate(newDate, component) - // // await validateExpiration(user, days, component) - // // }) - - // // test('new enforced default expiration date does not change existing expiration date', async () => { - // // const user = 'bob' - // // const days = 2 - // // const component = renderComponent({ - // // store: { - // // modules: { - // // user: { - // // state: { - // // capabilities: { - // // files_sharing: { - // // user: { - // // expire_date: { - // // enabled: true, - // // enforced: true, - // // days: '1' - // // } - // // } - // // } - // // } - // // } - // // } - // // } - // // }, - // // mocks: { - // // $client: { - // // ...sdkMock, - // // shares: { - // // ...sdkMock.shares, - // // getShares: jest.fn().mockImplementation(() => Promise.resolve(existingShares)) - // // } - // // } - // // } - // // }) - - // // await validateExpiration(user, days, component) - // // }) - // // }) - - // // https://github.com/owncloud/web/issues/3174 - // test.todo('enforced expiration date for groups does not affect user shares') - // test.todo('enforced expiration date for users does not affect group shares') - // }) -}) - -function createStore(store) { - return merge( - {}, - Store, - { - modules: { - config: { - getters: { - configuration: () => ({ - server: 'https://example.com', - options: {} - }) - } - }, - user: { - state: { - id: 'alice', - capabilities: { - files_sharing: { - search_min_length: 2, - group: { expire_date: { enabled: false } }, - user: { - send_mail: false, - profile_picture: true, - expire_date: { enabled: false } - } - } - } - } - }, - Files: merge({}, StoreFiles, { - state: { - incomingSharesLoading: false - }, - getters: { - highlightedFile: () => ({ - type: 'folder', - isFolder: true, - path: '/documents', - canShare: () => true - }), - currentFileOutgoingSharesLoading: () => false, - sharesTreeLoading: () => false - }, - actions: { - loadSharesTree: jest.fn - } - }) - } - }, - store - ) -} - -// eslint-disable-next-line no-unused-vars -function renderComponent({ store, mocks } = {}) { - return render( - FileShares, - { - store: createStore(store), - stubs: { - 'avatar-image': true - }, - routes, - mocks - }, - (vue, store, router) => { - router.push(createLocationSpaces('files-spaces-personal-home')) - } - ) -} - -async function getListItem(user, component) { - const { findByTestId } = component - return await findByTestId(selectors.listItem.containerPrefix + user) -} - -// eslint-disable-next-line no-unused-vars -async function searchUser(user, component) { - const { findByTestId, baseElement } = component - expect(await findByTestId(selectors.inviteForm.container)).toBeVisible() - await fireEvent.focus(baseElement.querySelector(selectors.inviteForm.input)) - await fireEvent.update(baseElement.querySelector(selectors.inviteForm.input), user) - await waitFor(() => expect(baseElement.querySelector(selectors.autocomplete.list)).toBeVisible()) -} - -// eslint-disable-next-line no-unused-vars -async function selectUser(user, component) { - const { findByTestId } = component - const userInAutocomplete = await findByTestId(selectors.autocomplete.itemPrefix + user) - expect(userInAutocomplete).toBeVisible() - userEvent.click(userInAutocomplete) - expect(await findByTestId(selectors.selectedRecipient.containerPrefix + user)).toBeVisible() -} - -// async function showEditDropdown(user, component) { -// const listItem = await getListItem(user, component) -// const editRecipientBtn = await within(listItem).getByTestId(selectors.listItem.editBtn) -// expect(editRecipientBtn).toBeVisible() -// await fireEvent.click(editRecipientBtn) -// } -// -// async function removeExpiration(user, component) { -// const listItem = await getListItem(user, component) -// const removeExpirationBtn = await within(listItem).findByTestId( -// selectors.listItem.removeExpirationBtn -// ) -// expect(removeExpirationBtn).toBeVisible() -// await fireEvent.click(removeExpirationBtn) -// } - -// eslint-disable-next-line no-unused-vars -async function triggerDatePicker(component) { - const { getByTestId } = component - expect(getByTestId(selectors.datepicker.container)).toBeVisible() - await fireEvent.click(getByTestId(selectors.datepicker.triggerBtn)) -} - -// eslint-disable-next-line no-unused-vars -async function validateInviteExpiration(days, component) { - const { findByTestId } = component - const inviteForm = await findByTestId(selectors.inviteForm.container) - expect( - await within(inviteForm).findByText(days === 1 ? 'Expires in 1 day' : `Expires in ${days} days`) - ).toBeVisible() -} - -// eslint-disable-next-line no-unused-vars -async function submitInvite(component) { - const { getByTestId, baseElement } = component - const shareBtn = getByTestId(selectors.inviteForm.createBtn) - expect(shareBtn).toBeVisible() - expect(shareBtn).not.toBeDisabled() - await fireEvent.click(shareBtn) - await waitFor(() => { - return expect(baseElement.querySelector(selectors.inviteForm.input)).toBeEmpty() - }) -} - -// eslint-disable-next-line no-unused-vars -async function validateExpiration(user, days, component) { - const listItem = await getListItem(user, component) - expect(listItem).toBeVisible() - expect( - await within(listItem).findByText(days === 1 ? 'Expires in 1 day' : `Expires in ${days} days`) - ).toBeVisible() -} diff --git a/packages/web-app-files/tests/unit/views/spaces/Trashbin.spec.js b/packages/web-app-files/tests/unit/views/spaces/Trashbin.spec.js index fe73d98faf4..49cd45f03d6 100644 --- a/packages/web-app-files/tests/unit/views/spaces/Trashbin.spec.js +++ b/packages/web-app-files/tests/unit/views/spaces/Trashbin.spec.js @@ -3,7 +3,7 @@ import { mount, createLocalVue } from '@vue/test-utils' import Trashbin from '@files/src/views/spaces/Trashbin.vue' import { createStore } from 'vuex-extensions' import { createLocationTrash } from '../../../../src/router' -import { waitFor } from '@testing-library/dom' +import waitFor from 'wait-for-expect' const localVue = createLocalVue() localVue.use(Vuex) diff --git a/tests/e2e/README.md b/tests/e2e/README.md index 94c0dc85c46..886b675ef26 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -10,11 +10,6 @@ forget some test steps. The main problem we faced, was that it's never a good th To get closer to the point where we are able to release faster and more often, we started to develop the end to end test suite. -## Structure - -Currently, we only have cucumber tests in place (wrapping the playwright library), but maybe in the future we will also adopt playwright -and its own test suite to replace our integration tests. - ## Run end to end cucumber tests Please make sure to point http://host.docker.internal/ to 127.0.0.1 by adding it to your hosts. diff --git a/tests/integration/config/jest.config.js b/tests/integration/config/jest.config.js deleted file mode 100644 index e683a0f975a..00000000000 --- a/tests/integration/config/jest.config.js +++ /dev/null @@ -1,31 +0,0 @@ -const path = require('path') -const rootDir = path.resolve(__dirname, '../../../') - -module.exports = { - rootDir, - modulePaths: [''], - moduleFileExtensions: ['js', 'ts', 'json', 'vue'], - transform: { - '^.+\\.(ts|tsx)$': 'ts-jest', - '^.+\\.js$': ['babel-jest', { configFile: path.join(rootDir, '.babelrc') }], - '^.+\\.vue$': 'vue-jest', - '^.+\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': - '/__mocks__/file.js' - }, - moduleNameMapper: { - '^.+\\.(css|scss)$': 'babel-jest', - '^@runtime/(.*)$': '/packages/web-runtime/$1', - '^@pkg/(.*)$': '/packages/web-pkg/$1', - '^@files/(.*)$': '/packages/web-app-files/$1', - '^@/(.*)$': '/$1', - '^core-js/(.*)$': '/node_modules/core-js/$1' - }, - testEnvironment: 'jsdom', - transformIgnorePatterns: ['/node_modules/(?!lodash-es)'], - setupFiles: ['/tests/integration/config/jest.init.js'], - snapshotSerializers: ['jest-serializer-vue'], - coverageDirectory: '/coverage/integration', - coverageReporters: ['lcov'], - collectCoverageFrom: ['/packages/**/src/**/*.{js,vue}', '!/**/node_modules/**'], - testMatch: ['**/tests/integration/specs/**/*.spec.js'] -} diff --git a/tests/integration/config/jest.init.js b/tests/integration/config/jest.init.js deleted file mode 100644 index b154af28a60..00000000000 --- a/tests/integration/config/jest.init.js +++ /dev/null @@ -1,46 +0,0 @@ -import Vue from 'vue' -import { config } from '@vue/test-utils' -import fetchMock from 'jest-fetch-mock' -import ODS from 'owncloud-design-system' -import GetTextPlugin from 'vue-gettext' -import VueCompositionAPI from '@vue/composition-api' - -// eslint-disable-next-line jest/no-mocks-import -import sdkMock from '../../../__mocks__/sdk' -import { encodePath } from '@pkg/src/utils' - -window.IntersectionObserver = jest.fn(() => ({ - observe: jest.fn(), - disconnect: jest.fn(), - unobserve: jest.fn() -})) - -Vue.use(ODS) -Vue.use(VueCompositionAPI) - -Vue.use(GetTextPlugin, { - availableLanguages: ['en'], - defaultLanguage: 'en', - translations: {} -}) - -fetchMock.enableMocks() - -try { - jest.setMock('cross-fetch', fetchMock) - jest.setMock('sync-fetch', fetchMock) -} catch (error) { - console.error(error) -} - -// since silent doesn't seem to work in test env for gettext plugin -// we're manually silencing all warn messages -console.warn = jest.fn() - -config.mocks = { - $client: sdkMock, - $clientService: { - owncloudSdk: sdkMock - }, - encodePath -} diff --git a/tests/unit/config/jest.config.js b/tests/unit/config/jest.config.js index d7a49e1dbe9..94db9060a42 100644 --- a/tests/unit/config/jest.config.js +++ b/tests/unit/config/jest.config.js @@ -27,6 +27,5 @@ module.exports = { '/packages/**/src/**/*.{js,ts,vue}', '!/**/node_modules/**' ], - testMatch: ['**/*.spec.{js,ts}'], - modulePathIgnorePatterns: ['integration'] + testMatch: ['**/*.spec.{js,ts}'] } diff --git a/yarn.lock b/yarn.lock index 098de017779..2eee9a2729a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1415,7 +1415,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.14.0, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.9.2": +"@babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.14.0, @babel/runtime@npm:^7.8.4": version: 7.17.2 resolution: "@babel/runtime@npm:7.17.2" dependencies: @@ -1897,19 +1897,6 @@ __metadata: languageName: node linkType: hard -"@jest/types@npm:^26.6.2": - version: 26.6.2 - resolution: "@jest/types@npm:26.6.2" - dependencies: - "@types/istanbul-lib-coverage": ^2.0.0 - "@types/istanbul-reports": ^3.0.0 - "@types/node": "*" - "@types/yargs": ^15.0.0 - chalk: ^4.0.0 - checksum: a0bd3d2f22f26ddb23f41fddf6e6a30bf4fab2ce79ec1cb6ce6fdfaf90a72e00f4c71da91ec61e13db3b10c41de22cf49d07c57ff2b59171d64b29f909c1d8d6 - languageName: node - linkType: hard - "@jest/types@npm:^27.2.5, @jest/types@npm:^27.4.2": version: 27.4.2 resolution: "@jest/types@npm:27.4.2" @@ -2181,80 +2168,6 @@ __metadata: languageName: node linkType: hard -"@testing-library/dom@npm:^7.26.6": - version: 7.31.2 - resolution: "@testing-library/dom@npm:7.31.2" - dependencies: - "@babel/code-frame": ^7.10.4 - "@babel/runtime": ^7.12.5 - "@types/aria-query": ^4.2.0 - aria-query: ^4.2.2 - chalk: ^4.1.0 - dom-accessibility-api: ^0.5.6 - lz-string: ^1.4.4 - pretty-format: ^26.6.2 - checksum: 54fbedd1ecdfe1d47be2e592b98d18b2ab9d7e731f57231caf9b152593fe7329fe5ebe219e0e5d1e0df5b1ab803121cb8acd8b73bd1fb292bfdc2c55663eb01d - languageName: node - linkType: hard - -"@testing-library/dom@npm:^8.11.0": - version: 8.11.0 - resolution: "@testing-library/dom@npm:8.11.0" - dependencies: - "@babel/code-frame": ^7.10.4 - "@babel/runtime": ^7.12.5 - "@types/aria-query": ^4.2.0 - aria-query: ^5.0.0 - chalk: ^4.1.0 - dom-accessibility-api: ^0.5.9 - lz-string: ^1.4.4 - pretty-format: ^27.0.2 - checksum: e546ef5c2d934fedce1d296763694151dfcb0f25a34301fce83f813924c1bc7926740c7036a2395bd611cbaa2dd604b11508d7bf10231f278400fffb8186f402 - languageName: node - linkType: hard - -"@testing-library/jest-dom@npm:^5.16.1": - version: 5.16.1 - resolution: "@testing-library/jest-dom@npm:5.16.1" - dependencies: - "@babel/runtime": ^7.9.2 - "@types/testing-library__jest-dom": ^5.9.1 - aria-query: ^5.0.0 - chalk: ^3.0.0 - css: ^3.0.0 - css.escape: ^1.5.1 - dom-accessibility-api: ^0.5.6 - lodash: ^4.17.15 - redent: ^3.0.0 - checksum: c5e3b5b021b50478137f96b85f8f6f86d2b25555d2501548982e093986f9c089c7b394449c30283ca3e28a50e845587403d9124ad1b516c55cf9af20a0fbbde4 - languageName: node - linkType: hard - -"@testing-library/user-event@npm:^13.5.0": - version: 13.5.0 - resolution: "@testing-library/user-event@npm:13.5.0" - dependencies: - "@babel/runtime": ^7.12.5 - peerDependencies: - "@testing-library/dom": ">=7.21.4" - checksum: 16319de685fbb7008f1ba667928f458b2d08196918002daca56996de80ef35e6d9de26e9e1ece7d00a004692b95a597cf9142fff0dc53f2f51606a776584f549 - languageName: node - linkType: hard - -"@testing-library/vue@npm:^5.8.2": - version: 5.8.2 - resolution: "@testing-library/vue@npm:5.8.2" - dependencies: - "@babel/runtime": ^7.12.5 - "@testing-library/dom": ^7.26.6 - "@vue/test-utils": ^1.1.0 - peerDependencies: - vue: ^2.6.10 - vue-template-compiler: ^2.6.10 - checksum: 31e320e353fa0bd89371a0de92f6fdf5f816b608a3b0d3d86e77ef56732b07b7e9f6069d38e17115f80863587ecccacdffaa524a474383260e342d72189a9d1f - languageName: node - linkType: hard - "@tootallnate/once@npm:1": version: 1.1.2 resolution: "@tootallnate/once@npm:1.1.2" @@ -2297,13 +2210,6 @@ __metadata: languageName: node linkType: hard -"@types/aria-query@npm:^4.2.0": - version: 4.2.1 - resolution: "@types/aria-query@npm:4.2.1" - checksum: cf60cc7aa0ed52514e8c7289776de9bb3321217d48f54c95d63e1e1eb9940689c1fd3e39d68da5eaee1541108363f0113007f67d6e32e7fbc983526f08e5f0ce - languageName: node - linkType: hard - "@types/babel__core@npm:^7.0.0, @types/babel__core@npm:^7.1.14": version: 7.1.14 resolution: "@types/babel__core@npm:7.1.14" @@ -2565,15 +2471,6 @@ __metadata: languageName: node linkType: hard -"@types/testing-library__jest-dom@npm:^5.9.1": - version: 5.14.0 - resolution: "@types/testing-library__jest-dom@npm:5.14.0" - dependencies: - "@types/jest": "*" - checksum: dc42909d5afb907f82a2ad29d77bb8ed8bff17ad3090586cec18742dd94d7ce533ac0a4571ffd93ccfa6f54a02d991a3ba561361cb72107df754b8ed7a8b04ae - languageName: node - linkType: hard - "@types/ua-parser-js@npm:^0.7.36": version: 0.7.36 resolution: "@types/ua-parser-js@npm:0.7.36" @@ -2602,15 +2499,6 @@ __metadata: languageName: node linkType: hard -"@types/yargs@npm:^15.0.0": - version: 15.0.13 - resolution: "@types/yargs@npm:15.0.13" - dependencies: - "@types/yargs-parser": "*" - checksum: a6ebb0ec63f168280e02370fcf24ff29c3eb0335e1c46e3b34e04d32eb7c818446e0b7de8badb339b07c0ddba322827ce13ccb604d14a0de422335ae56b2120d - languageName: node - linkType: hard - "@types/yargs@npm:^16.0.0": version: 16.0.4 resolution: "@types/yargs@npm:16.0.4" @@ -3001,7 +2889,7 @@ __metadata: languageName: node linkType: hard -"@vue/test-utils@npm:^1.1.0, @vue/test-utils@npm:^1.3.0": +"@vue/test-utils@npm:^1.3.0": version: 1.3.0 resolution: "@vue/test-utils@npm:1.3.0" dependencies: @@ -3233,7 +3121,7 @@ __metadata: languageName: node linkType: hard -"ansi-regex@npm:^5.0.0, ansi-regex@npm:^5.0.1": +"ansi-regex@npm:^5.0.1": version: 5.0.1 resolution: "ansi-regex@npm:5.0.1" checksum: 2aa4bb54caf2d622f1afdad09441695af2a83aa3fe8b8afa581d205e57ed4261c183c4d3877cee25794443fde5876417d859c108078ab788d6af7e4fe52eb66b @@ -3344,13 +3232,6 @@ __metadata: languageName: node linkType: hard -"aria-query@npm:^5.0.0": - version: 5.0.0 - resolution: "aria-query@npm:5.0.0" - checksum: c41f98866c5a304561ee8cae55856711cddad6f3f85d8cb43cc5f79667078d9b8979ce32d244c1ff364e6463a4d0b6865804a33ccc717fed701b281cf7dc6296 - languageName: node - linkType: hard - "array-differ@npm:^3.0.0": version: 3.0.0 resolution: "array-differ@npm:3.0.0" @@ -4197,16 +4078,6 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^3.0.0": - version: 3.0.0 - resolution: "chalk@npm:3.0.0" - dependencies: - ansi-styles: ^4.1.0 - supports-color: ^7.1.0 - checksum: 8e3ddf3981c4da405ddbd7d9c8d91944ddf6e33d6837756979f7840a29272a69a5189ecae0ff84006750d6d1e92368d413335eab4db5476db6e6703a1d1e0505 - languageName: node - linkType: hard - "chalk@npm:^4.0.0, chalk@npm:^4.1.0, chalk@npm:^4.1.1, chalk@npm:^4.1.2": version: 4.1.2 resolution: "chalk@npm:4.1.2" @@ -4869,13 +4740,6 @@ __metadata: languageName: node linkType: hard -"css.escape@npm:^1.5.1": - version: 1.5.1 - resolution: "css.escape@npm:1.5.1" - checksum: f6d38088d870a961794a2580b2b2af1027731bb43261cfdce14f19238a88664b351cc8978abc20f06cc6bbde725699dec8deb6fe9816b139fc3f2af28719e774 - languageName: node - linkType: hard - "css@npm:^2.0.0, css@npm:^2.1.0": version: 2.2.4 resolution: "css@npm:2.2.4" @@ -4888,17 +4752,6 @@ __metadata: languageName: node linkType: hard -"css@npm:^3.0.0": - version: 3.0.0 - resolution: "css@npm:3.0.0" - dependencies: - inherits: ^2.0.4 - source-map: ^0.6.1 - source-map-resolve: ^0.6.0 - checksum: 4273ac816ddf99b99acb9c1d1a27d86d266a533cc01118369d941d8e8a78277a83cad3315e267a398c509d930fbb86504e193ea1ebc620a4a4212e06fe76e8be - languageName: node - linkType: hard - "cssesc@npm:^3.0.0": version: 3.0.0 resolution: "cssesc@npm:3.0.0" @@ -5358,13 +5211,6 @@ __metadata: languageName: node linkType: hard -"dom-accessibility-api@npm:^0.5.6, dom-accessibility-api@npm:^0.5.9": - version: 0.5.10 - resolution: "dom-accessibility-api@npm:0.5.10" - checksum: c05949889b02f5313d100778e9f736f9bddfb1da47387d351833f0b5d60d6230d4fcb849e124a8a1591706b6200337fa40f0f4f3817dce1459309e075f48371c - languageName: node - linkType: hard - "dom-event-types@npm:^1.0.0": version: 1.0.0 resolution: "dom-event-types@npm:1.0.0" @@ -7229,7 +7075,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": +"inherits@npm:2, inherits@npm:^2.0.3, inherits@npm:~2.0.3": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 @@ -8948,15 +8794,6 @@ __metadata: languageName: node linkType: hard -"lz-string@npm:^1.4.4": - version: 1.4.4 - resolution: "lz-string@npm:1.4.4" - bin: - lz-string: bin/bin.js - checksum: 54e31238a61a84d8f664d9860a9fba7310c5b97a52c444f80543069bc084815eff40b8d4474ae1d93992fdf6c252dca37cf27f6adbeb4dbc3df2f3ac773d0e61 - languageName: node - linkType: hard - "magic-string@npm:0.25.2": version: 0.25.2 resolution: "magic-string@npm:0.25.2" @@ -9166,13 +9003,6 @@ __metadata: languageName: node linkType: hard -"min-indent@npm:^1.0.0": - version: 1.0.1 - resolution: "min-indent@npm:1.0.1" - checksum: bfc6dd03c5eaf623a4963ebd94d087f6f4bbbfd8c41329a7f09706b0cb66969c4ddd336abeb587bc44bc6f08e13bf90f0b374f9d71f9f01e04adc2cd6f083ef1 - languageName: node - linkType: hard - "minimatch@npm:3.0.4, minimatch@npm:^3.0.4": version: 3.0.4 resolution: "minimatch@npm:3.0.4" @@ -10895,18 +10725,6 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^26.6.2": - version: 26.6.2 - resolution: "pretty-format@npm:26.6.2" - dependencies: - "@jest/types": ^26.6.2 - ansi-regex: ^5.0.0 - ansi-styles: ^4.0.0 - react-is: ^17.0.1 - checksum: e3b808404d7e1519f0df1aa1f25cee0054ab475775c6b2b8c5568ff23194a92d54bf93274139b6f584ca70fd773be4eaa754b0e03f12bb0a8d1426b07f079976 - languageName: node - linkType: hard - "pretty-format@npm:^27.0.0, pretty-format@npm:^27.0.2, pretty-format@npm:^27.2.5, pretty-format@npm:^27.4.6, pretty-format@npm:^27.5.1": version: 27.5.1 resolution: "pretty-format@npm:27.5.1" @@ -11387,16 +11205,6 @@ __metadata: languageName: node linkType: hard -"redent@npm:^3.0.0": - version: 3.0.0 - resolution: "redent@npm:3.0.0" - dependencies: - indent-string: ^4.0.0 - strip-indent: ^3.0.0 - checksum: fa1ef20404a2d399235e83cc80bd55a956642e37dd197b4b612ba7327bf87fa32745aeb4a1634b2bab25467164ab4ed9c15be2c307923dd08b0fe7c52431ae6b - languageName: node - linkType: hard - "reflect-metadata@npm:0.1.13": version: 0.1.13 resolution: "reflect-metadata@npm:0.1.13" @@ -11922,10 +11730,6 @@ __metadata: "@rollup/plugin-inject": ^4.0.4 "@rollup/plugin-json": ^4.1.0 "@rollup/plugin-typescript": ^8.3.0 - "@testing-library/dom": ^8.11.0 - "@testing-library/jest-dom": ^5.16.1 - "@testing-library/user-event": ^13.5.0 - "@testing-library/vue": ^5.8.2 "@types/jest": ^27.4.1 "@types/jest-axe": ^3.5.3 "@types/lodash-es": ^4.17.5 @@ -12000,6 +11804,7 @@ __metadata: vue-jest: ^3.0.7 vue-template-compiler: ^2.6.12 vuex-mock-store: 0.0.8 + wait-for-expect: ^3.0.2 dependenciesMeta: "@playwright/test": built: true @@ -12351,16 +12156,6 @@ __metadata: languageName: node linkType: hard -"source-map-resolve@npm:^0.6.0": - version: 0.6.0 - resolution: "source-map-resolve@npm:0.6.0" - dependencies: - atob: ^2.1.2 - decode-uri-component: ^0.2.0 - checksum: fe503b9e5dac1c54be835282fcfec10879434e7b3ee08a9774f230299c724a8d403484d9531276d1670c87390e0e4d1d3f92b14cca6e4a2445ea3016b786ecd4 - languageName: node - linkType: hard - "source-map-support@npm:0.4.18": version: 0.4.18 resolution: "source-map-support@npm:0.4.18" @@ -12717,15 +12512,6 @@ __metadata: languageName: node linkType: hard -"strip-indent@npm:^3.0.0": - version: 3.0.0 - resolution: "strip-indent@npm:3.0.0" - dependencies: - min-indent: ^1.0.0 - checksum: 18f045d57d9d0d90cd16f72b2313d6364fd2cb4bf85b9f593523ad431c8720011a4d5f08b6591c9d580f446e78855c5334a30fb91aa1560f5d9f95ed1b4a0530 - languageName: node - linkType: hard - "strip-json-comments@npm:^2.0.0": version: 2.0.1 resolution: "strip-json-comments@npm:2.0.1" @@ -13886,6 +13672,13 @@ __metadata: languageName: node linkType: hard +"wait-for-expect@npm:^3.0.2": + version: 3.0.2 + resolution: "wait-for-expect@npm:3.0.2" + checksum: 2ec1ebd78023fa10bdcf53d78bbd65feea68fdfa0de0b00f3a72f3df089118b91517839ff3926e5ef6cfd1ede65085326d85b0378d4db62c266cc9c859c2de56 + languageName: node + linkType: hard + "walker@npm:^1.0.7": version: 1.0.7 resolution: "walker@npm:1.0.7"