diff --git a/test/e2e/package.json b/test/e2e/package.json index 57bf50e..9cc0067 100644 --- a/test/e2e/package.json +++ b/test/e2e/package.json @@ -12,6 +12,7 @@ "allure-commandline": "^2.38.1", "cloudinary": "^2.9.0", "expect-webdriverio": "^5.6.5", + "wdio-video-reporter": "^6.2.0", "wdio-vscode-service": "^6.1.4", "webdriverio": "^9.27.0" }, diff --git a/test/e2e/pnpm-lock.yaml b/test/e2e/pnpm-lock.yaml index a0112d0..e8f9f44 100644 --- a/test/e2e/pnpm-lock.yaml +++ b/test/e2e/pnpm-lock.yaml @@ -38,6 +38,9 @@ importers: expect-webdriverio: specifier: ^5.6.5 version: 5.6.5(@wdio/globals@9.27.0)(@wdio/logger@9.18.0)(webdriverio@9.27.0) + wdio-video-reporter: + specifier: ^6.2.0 + version: 6.2.0(expect-webdriverio@5.6.5)(webdriverio@9.27.0) wdio-vscode-service: specifier: ^6.1.4 version: 6.1.4(webdriverio@9.27.0) @@ -243,6 +246,49 @@ packages: '@fastify/static@7.0.4': resolution: {integrity: sha512-p2uKtaf8BMOZWLs6wu+Ihg7bWNBdjNgCwDza4MJtTqg+5ovKmcbgbR9Xs5/smZ1YISfzKOCNYmZV8LaCj+eJ1Q==} + '@ffmpeg-installer/darwin-arm64@4.1.5': + resolution: {integrity: sha512-hYqTiP63mXz7wSQfuqfFwfLOfwwFChUedeCVKkBtl/cliaTM7/ePI9bVzfZ2c+dWu3TqCwLDRWNSJ5pqZl8otA==} + cpu: [arm64] + os: [darwin] + + '@ffmpeg-installer/darwin-x64@4.1.0': + resolution: {integrity: sha512-Z4EyG3cIFjdhlY8wI9aLUXuH8nVt7E9SlMVZtWvSPnm2sm37/yC2CwjUzyCQbJbySnef1tQwGG2Sx+uWhd9IAw==} + cpu: [x64] + os: [darwin] + + '@ffmpeg-installer/ffmpeg@1.1.0': + resolution: {integrity: sha512-Uq4rmwkdGxIa9A6Bd/VqqYbT7zqh1GrT5/rFwCwKM70b42W5gIjWeVETq6SdcL0zXqDtY081Ws/iJWhr1+xvQg==} + + '@ffmpeg-installer/linux-arm64@4.1.4': + resolution: {integrity: sha512-dljEqAOD0oIM6O6DxBW9US/FkvqvQwgJ2lGHOwHDDwu/pX8+V0YsDL1xqHbj1DMX/+nP9rxw7G7gcUvGspSoKg==} + cpu: [arm64] + os: [linux] + + '@ffmpeg-installer/linux-arm@4.1.3': + resolution: {integrity: sha512-NDf5V6l8AfzZ8WzUGZ5mV8O/xMzRag2ETR6+TlGIsMHp81agx51cqpPItXPib/nAZYmo55Bl2L6/WOMI3A5YRg==} + cpu: [arm] + os: [linux] + + '@ffmpeg-installer/linux-ia32@4.1.0': + resolution: {integrity: sha512-0LWyFQnPf+Ij9GQGD034hS6A90URNu9HCtQ5cTqo5MxOEc7Rd8gLXrJvn++UmxhU0J5RyRE9KRYstdCVUjkNOQ==} + cpu: [ia32] + os: [linux] + + '@ffmpeg-installer/linux-x64@4.1.0': + resolution: {integrity: sha512-Y5BWhGLU/WpQjOArNIgXD3z5mxxdV8c41C+U15nsE5yF8tVcdCGet5zPs5Zy3Ta6bU7haGpIzryutqCGQA/W8A==} + cpu: [x64] + os: [linux] + + '@ffmpeg-installer/win32-ia32@4.1.0': + resolution: {integrity: sha512-FV2D7RlaZv/lrtdhaQ4oETwoFUsUjlUiasiZLDxhEUPdNDWcH1OU9K1xTvqz+OXLdsmYelUDuBS/zkMOTtlUAw==} + cpu: [ia32] + os: [win32] + + '@ffmpeg-installer/win32-x64@4.1.0': + resolution: {integrity: sha512-Drt5u2vzDnIONf4ZEkKtFlbvwj6rI3kxw1Ck9fpudmtgaZIHD4ucsWB2lCZBXRxJgXR+2IMSti+4rtM4C4rXgg==} + cpu: [x64] + os: [win32] + '@inquirer/ansi@1.0.2': resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} engines: {node: '>=18'} @@ -381,6 +427,10 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + '@isaacs/cliui@9.0.0': + resolution: {integrity: sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==} + engines: {node: '>=18'} + '@jest/diff-sequences@30.3.0': resolution: {integrity: sha512-cG51MVnLq1ecVUaQ3fr6YuuAOitHK1S4WUJHnsPFE/quQr33ADUx1FfrTCpMCRxvy0Yr9BThKpDjSlcTi91tMA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -742,6 +792,10 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + bare-events@2.8.2: resolution: {integrity: sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==} peerDependencies: @@ -803,6 +857,10 @@ packages: brace-expansion@2.0.3: resolution: {integrity: sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==} + brace-expansion@5.0.5: + resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} + engines: {node: 18 || 20 || >=22} + braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} @@ -1349,6 +1407,12 @@ packages: resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} hasBin: true + glob@11.1.0: + resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} + engines: {node: 20 || >=22} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + glob@8.1.0: resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} engines: {node: '>=12'} @@ -1546,6 +1610,10 @@ packages: jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jackspeak@4.2.3: + resolution: {integrity: sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==} + engines: {node: 20 || >=22} + jake@10.9.4: resolution: {integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==} engines: {node: '>=10'} @@ -1674,6 +1742,10 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@11.3.6: + resolution: {integrity: sha512-Gf/KoL3C/MlI7Bt0PGI9I+TeTC/I6r/csU58N4BSNc4lppLBeKsOdFYkK+dX0ABDUMJNfCHTyPpzwwO21Awd3A==} + engines: {node: 20 || >=22} + lru-cache@7.18.3: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} @@ -1712,6 +1784,10 @@ packages: resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + minimatch@10.2.5: + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} + minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} @@ -1881,6 +1957,10 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} + pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} @@ -2368,6 +2448,9 @@ packages: wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + wdio-video-reporter@6.2.0: + resolution: {integrity: sha512-b/LHQFluxIcP7foWW0gJ/5W6x1NsTVzJ2yiZZ+W4ETtYBUFU0Xfd2fYVC3q3Uxb3He6QkuNT+h0xCefJSZRyVg==} + wdio-vscode-service@6.1.4: resolution: {integrity: sha512-doPxz6YzwcQ9V8BEdxk+3gvqRzkA1D3XkqyDV+8WczBtc4KhbkPvwxfB0LUPB/7D9RA3we+gOoIhbISzELIr/A==} engines: {node: ^16.13 || >=18} @@ -2621,6 +2704,41 @@ snapshots: fastq: 1.20.1 glob: 10.5.0 + '@ffmpeg-installer/darwin-arm64@4.1.5': + optional: true + + '@ffmpeg-installer/darwin-x64@4.1.0': + optional: true + + '@ffmpeg-installer/ffmpeg@1.1.0': + optionalDependencies: + '@ffmpeg-installer/darwin-arm64': 4.1.5 + '@ffmpeg-installer/darwin-x64': 4.1.0 + '@ffmpeg-installer/linux-arm': 4.1.3 + '@ffmpeg-installer/linux-arm64': 4.1.4 + '@ffmpeg-installer/linux-ia32': 4.1.0 + '@ffmpeg-installer/linux-x64': 4.1.0 + '@ffmpeg-installer/win32-ia32': 4.1.0 + '@ffmpeg-installer/win32-x64': 4.1.0 + + '@ffmpeg-installer/linux-arm64@4.1.4': + optional: true + + '@ffmpeg-installer/linux-arm@4.1.3': + optional: true + + '@ffmpeg-installer/linux-ia32@4.1.0': + optional: true + + '@ffmpeg-installer/linux-x64@4.1.0': + optional: true + + '@ffmpeg-installer/win32-ia32@4.1.0': + optional: true + + '@ffmpeg-installer/win32-x64@4.1.0': + optional: true + '@inquirer/ansi@1.0.2': {} '@inquirer/checkbox@4.3.2(@types/node@25.5.2)': @@ -2755,6 +2873,8 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + '@isaacs/cliui@9.0.0': {} + '@jest/diff-sequences@30.3.0': {} '@jest/expect-utils@30.3.0': @@ -3290,6 +3410,8 @@ snapshots: balanced-match@1.0.2: {} + balanced-match@4.0.4: {} + bare-events@2.8.2: {} bare-fs@4.6.0: @@ -3339,6 +3461,10 @@ snapshots: dependencies: balanced-match: 1.0.2 + brace-expansion@5.0.5: + dependencies: + balanced-match: 4.0.4 + braces@3.0.3: dependencies: fill-range: 7.1.1 @@ -3968,6 +4094,15 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 + glob@11.1.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 4.2.3 + minimatch: 10.2.5 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.2 + glob@8.1.0: dependencies: fs.realpath: 1.0.0 @@ -4147,6 +4282,10 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jackspeak@4.2.3: + dependencies: + '@isaacs/cliui': 9.0.0 + jake@10.9.4: dependencies: async: 3.2.6 @@ -4287,6 +4426,8 @@ snapshots: lru-cache@10.4.3: {} + lru-cache@11.3.6: {} + lru-cache@7.18.3: {} magic-string@0.30.21: @@ -4313,6 +4454,10 @@ snapshots: mimic-response@4.0.0: {} + minimatch@10.2.5: + dependencies: + brace-expansion: 5.0.5 + minimatch@3.1.5: dependencies: brace-expansion: 1.1.13 @@ -4501,6 +4646,11 @@ snapshots: lru-cache: 10.4.3 minipass: 7.1.3 + path-scurry@2.0.2: + dependencies: + lru-cache: 11.3.6 + minipass: 7.1.3 + pathe@1.1.2: {} pathe@2.0.3: {} @@ -4982,6 +5132,20 @@ snapshots: defaults: 1.0.4 optional: true + wdio-video-reporter@6.2.0(expect-webdriverio@5.6.5)(webdriverio@9.27.0): + dependencies: + '@ffmpeg-installer/ffmpeg': 1.1.0 + '@wdio/allure-reporter': 9.27.0 + '@wdio/globals': 9.27.0(expect-webdriverio@5.6.5)(webdriverio@9.27.0) + '@wdio/logger': 9.18.0 + '@wdio/reporter': 9.27.0 + '@wdio/types': 9.27.0 + glob: 11.1.0 + transitivePeerDependencies: + - allure-playwright + - expect-webdriverio + - webdriverio + wdio-vscode-service@6.1.4(webdriverio@9.27.0): dependencies: '@fastify/cors': 9.0.1 diff --git a/test/e2e/specs/searchAssetFromSideBar.spec.ts b/test/e2e/specs/searchAssetFromSideBar.spec.ts index 4e002be..e37a2dc 100644 --- a/test/e2e/specs/searchAssetFromSideBar.spec.ts +++ b/test/e2e/specs/searchAssetFromSideBar.spec.ts @@ -34,6 +34,7 @@ describe('Search asset from side bar', () => { it('should find the uploaded asset via sidebar search', async () => { await activityBarUtils.openView('Cloudinary'); await sideBarViewUtils.homeScreenViewPage.clickBrowseLibraryButton(); + await sideBarViewUtils.waitContentToLoad(); await sideBarViewUtils.clickAction(SideBarViewActions.SEARCH); diff --git a/test/e2e/specs/uploadFromSideBarView.spec.ts b/test/e2e/specs/uploadFromSideBarView.spec.ts index 0a466e8..e520879 100644 --- a/test/e2e/specs/uploadFromSideBarView.spec.ts +++ b/test/e2e/specs/uploadFromSideBarView.spec.ts @@ -50,7 +50,9 @@ describe('Upload asset from side bar Upload button', () => { await uploadToCloudinaryTab.switchBack(); await activityBarUtils.openView('Cloudinary'); - + + await cloudinarySDK.waitUntilAssetIsUploaded(firstAssetPublicID); + await sideBarViewUtils.clickAction(SideBarViewActions.REFRESH); await sideBarViewUtils.validateContentItemsExist([newFileName.replace('.png', '')]); diff --git a/test/e2e/src/sdks/cloudinarySDK.ts b/test/e2e/src/sdks/cloudinarySDK.ts index 773e473..8dd9aff 100644 --- a/test/e2e/src/sdks/cloudinarySDK.ts +++ b/test/e2e/src/sdks/cloudinarySDK.ts @@ -1,3 +1,4 @@ +import { browser } from '@wdio/globals'; import * as cloudinary from 'cloudinary'; /** Optional overrides; values fall back to `E2E_*` environment variables. */ @@ -36,4 +37,14 @@ export class CloudinarySDK { get V2(): typeof cloudinary.v2 { return cloudinary.v2; } + + /** + * Waits until the asset is uploaded and the display name is the expected one. + */ + public async waitUntilAssetIsUploaded(publicId: string) { + await browser.waitUntil(async () => { + const byPublicId = await this.V2.api.resource(publicId); + return byPublicId.public_id === publicId; + }, { timeout: 15000, timeoutMsg: 'Asset not uploaded in time' }); + } } diff --git a/test/e2e/src/vscodeComponentsUtils/SideBarViewUtils.ts b/test/e2e/src/vscodeComponentsUtils/SideBarViewUtils.ts index 5a4a8f1..0b01c5d 100644 --- a/test/e2e/src/vscodeComponentsUtils/SideBarViewUtils.ts +++ b/test/e2e/src/vscodeComponentsUtils/SideBarViewUtils.ts @@ -59,12 +59,20 @@ class SideBarViewUtils { public async validateContentItemsExist(expectedItems: string[]) { await allureReporter.addStep(`Validate content items exist: [${expectedItems.join(', ')}]`); await this.waitContentToLoad(); - const content = await this.getSideBarViewContent(); - const sections = await content.getSections(); - const visibleItems = await sections[0].getVisibleItems() as TreeItem[]; - const itemLabels = await Promise.all( - visibleItems.map(item => item.getLabel()) - ); + let itemLabels: string[] = []; + await browser.waitUntil(async () => { + try { + const content = await this.getSideBarViewContent(); + const sections = await content.getSections(); + const visibleItems = await sections[0].getVisibleItems() as TreeItem[]; + itemLabels = await Promise.all( + visibleItems.map(item => item.getLabel()) + ); + return itemLabels.includes(expectedItems[0]); + } catch { + return false; + } + }, { timeout: 15000, timeoutMsg: 'Timed out waiting for content items to be available' }); for (const expected of expectedItems) { expect(itemLabels).toContain(expected); diff --git a/test/e2e/wdio.conf.ts b/test/e2e/wdio.conf.ts index ea92826..3376690 100644 --- a/test/e2e/wdio.conf.ts +++ b/test/e2e/wdio.conf.ts @@ -3,6 +3,7 @@ import * as os from 'node:os'; import { fileURLToPath } from 'node:url'; import * as path from 'node:path'; import allureReporter from '@wdio/allure-reporter' +import video from 'wdio-video-reporter' const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -35,9 +36,7 @@ export const config: WebdriverIO.Config = { './specs/**/*.spec.ts' ], // Patterns to exclude. - exclude: [ - // 'path/to/excluded/files' - ], + exclude: [], // // ============ // Capabilities @@ -54,7 +53,7 @@ export const config: WebdriverIO.Config = { // and 30 processes will get spawned. The property handles how many capabilities // from the same test should run tests. // - maxInstances: 5, + maxInstances: process.env.CI ? 1 : 3, // // If you have trouble getting all important capabilities together, check out the // Sauce Labs platform configurator - a great tool to configure your capabilities: @@ -150,6 +149,11 @@ export const config: WebdriverIO.Config = { // see also: https://webdriver.io/docs/dot-reporter reporters: [ 'spec', + [video, { + saveAllVideos: false, + videoSlowdownMultiplier: 3, + outputDir: 'allure-results', + }], ['allure', { outputDir: 'allure-results', disableWebdriverStepsReporting: true,