diff --git a/packages/cli/package.json b/packages/cli/package.json index 3eb3846ac6..7e8c1e86c8 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -26,6 +26,12 @@ "test:postgres": "N8N_LOG_LEVEL=silent DB_TYPE=postgresdb DB_POSTGRESDB_SCHEMA=alt_schema DB_TABLE_PREFIX=test_ jest --no-coverage", "test:mariadb": "N8N_LOG_LEVEL=silent DB_TYPE=mariadb DB_TABLE_PREFIX=test_ jest --no-coverage", "test:mysql": "N8N_LOG_LEVEL=silent DB_TYPE=mysqldb DB_TABLE_PREFIX=test_ jest --no-coverage", + "test:win": "pnpm test:sqlite:win", + "test:dev:win": "set N8N_LOG_LEVEL=silent&& set DB_TYPE=sqlite&& jest --watch", + "test:sqlite:win": "set N8N_LOG_LEVEL=silent&& set DB_TYPE=sqlite&& jest", + "test:postgres:win": "set N8N_LOG_LEVEL=silent&& set DB_TYPE=postgresdb&& set DB_POSTGRESDB_SCHEMA=alt_schema&& set DB_TABLE_PREFIX=test_&& jest --no-coverage", + "test:mariadb:win": "set N8N_LOG_LEVEL=silent&& set DB_TYPE=mariadb&& set DB_TABLE_PREFIX=test_&& jest --no-coverage", + "test:mysql:win": "set N8N_LOG_LEVEL=silent&& set DB_TYPE=mysqldb&& set DB_TABLE_PREFIX=test_&& jest --no-coverage", "watch": "tsc-watch -p tsconfig.build.json --onCompilationComplete \"tsc-alias -p tsconfig.build.json\"" }, "bin": { diff --git a/packages/cli/src/modules/community-packages/__tests__/community-packages.service.test.ts b/packages/cli/src/modules/community-packages/__tests__/community-packages.service.test.ts index 9db83414c2..c2d4901b7d 100644 --- a/packages/cli/src/modules/community-packages/__tests__/community-packages.service.test.ts +++ b/packages/cli/src/modules/community-packages/__tests__/community-packages.service.test.ts @@ -1,5 +1,5 @@ import type { Logger } from '@n8n/backend-common'; -import { randomName, mockInstance } from '@n8n/backend-test-utils'; +import { mockInstance, randomName } from '@n8n/backend-test-utils'; import { LICENSE_FEATURES } from '@n8n/constants'; import axios from 'axios'; import { mocked } from 'jest-mock'; @@ -7,8 +7,8 @@ import { mock } from 'jest-mock-extended'; import type { InstanceSettings, PackageDirectoryLoader } from 'n8n-core'; import type { PublicInstalledPackage } from 'n8n-workflow'; import { exec } from 'node:child_process'; -import { mkdir, readFile, writeFile, rm, access, constants } from 'node:fs/promises'; -import { join } from 'node:path'; +import { access, constants, mkdir, readFile, rm, writeFile } from 'node:fs/promises'; +import path, { join } from 'node:path'; import { NODE_PACKAGE_PREFIX, @@ -54,7 +54,7 @@ describe('CommunityPackagesService', () => { const installedNodesRepository = mockInstance(InstalledNodesRepository); const installedPackageRepository = mockInstance(InstalledPackagesRepository); - const nodesDownloadDir = '/tmp/n8n-jest-global-downloads'; + const nodesDownloadDir = path.join('tmp', 'n8n-jest-global-downloads'); const instanceSettings = mock({ nodesDownloadDir }); const logger = mock(); @@ -441,7 +441,10 @@ describe('CommunityPackagesService', () => { // ASSERT: expect(rm).toHaveBeenCalledTimes(2); expect(rm).toHaveBeenNthCalledWith(1, testBlockPackageDir, { recursive: true, force: true }); - expect(rm).toHaveBeenNthCalledWith(2, `${nodesDownloadDir}/n8n-nodes-test-latest.tgz`); + expect(rm).toHaveBeenNthCalledWith( + 2, + path.join(nodesDownloadDir, 'n8n-nodes-test-latest.tgz'), + ); expect(exec).toHaveBeenCalledTimes(3); expect(exec).toHaveBeenNthCalledWith( @@ -672,7 +675,7 @@ describe('CommunityPackagesService', () => { await communityPackagesService.updatePackageJsonDependency('test-package', '1.0.0'); expect(writeFile).toHaveBeenCalledWith( - `${nodesDownloadDir}/package.json`, + path.join(nodesDownloadDir, 'package.json'), JSON.stringify({ dependencies: { 'test-package': '1.0.0' } }, null, 2), 'utf-8', ); @@ -682,7 +685,7 @@ describe('CommunityPackagesService', () => { await communityPackagesService.updatePackageJsonDependency('test-package', '1.0.0'); expect(writeFile).toHaveBeenCalledWith( - `${nodesDownloadDir}/package.json`, + path.join(nodesDownloadDir, 'package.json'), JSON.stringify({ dependencies: { 'test-package': '1.0.0' } }, null, 2), 'utf-8', ); diff --git a/packages/frontend/editor-ui/src/components/Node/NodeCreator/Panel/CommunityNodeFooter.test.ts b/packages/frontend/editor-ui/src/components/Node/NodeCreator/Panel/CommunityNodeFooter.test.ts index 3244e7edff..1ddbe0c51b 100644 --- a/packages/frontend/editor-ui/src/components/Node/NodeCreator/Panel/CommunityNodeFooter.test.ts +++ b/packages/frontend/editor-ui/src/components/Node/NodeCreator/Panel/CommunityNodeFooter.test.ts @@ -5,18 +5,16 @@ import { setActivePinia } from 'pinia'; import CommunityNodeFooter from './CommunityNodeFooter.vue'; import { createComponentRenderer } from '@/__tests__/render'; import { vi } from 'vitest'; -import type { PublicInstalledPackage } from 'n8n-workflow'; +import { type ExtendedPublicInstalledPackage, fetchInstalledPackageInfo } from './utils'; -const getInstalledPackage = vi.fn(); +vi.mock('./utils', () => ({ + fetchInstalledPackageInfo: vi.fn(), +})); + +const mockedFetchInstalledPackageInfo = vi.mocked(fetchInstalledPackageInfo); const push = vi.fn(); -const communityNodesStore: { - getInstalledPackage: (packageName: string) => Promise; -} = { - getInstalledPackage, -}; - vi.mock('vue-router', async (importOriginal) => { const actual = await importOriginal(); return { @@ -27,10 +25,6 @@ vi.mock('vue-router', async (importOriginal) => { }; }); -vi.mock('@/stores/communityNodes.store', () => ({ - useCommunityNodesStore: vi.fn(() => communityNodesStore), -})); - describe('CommunityNodeInfo - links & bugs URL', () => { beforeEach(() => { setActivePinia(createTestingPinia()); @@ -70,25 +64,27 @@ describe('CommunityNodeInfo - links & bugs URL', () => { }); it('displays "Legacy" when updateAvailable', async () => { - getInstalledPackage.mockResolvedValue({ + mockedFetchInstalledPackageInfo.mockResolvedValue({ installedVersion: '1.0.0', updateAvailable: '1.0.1', - } as PublicInstalledPackage); + unverifiedUpdate: false, + } as ExtendedPublicInstalledPackage); const { getByText } = createComponentRenderer(CommunityNodeFooter)({ props: { packageName: 'n8n-nodes-test', showManage: false, }, }); - await waitFor(() => expect(getInstalledPackage).toHaveBeenCalled()); + await waitFor(() => expect(mockedFetchInstalledPackageInfo).toHaveBeenCalled()); expect(getByText('Package version 1.0.0 (Legacy)')).toBeInTheDocument(); }); it('displays "Latest" when not updateAvailable', async () => { - getInstalledPackage.mockResolvedValue({ + mockedFetchInstalledPackageInfo.mockResolvedValue({ installedVersion: '1.0.0', - } as PublicInstalledPackage); + unverifiedUpdate: false, + } as ExtendedPublicInstalledPackage); const { getByText } = createComponentRenderer(CommunityNodeFooter)({ props: { packageName: 'n8n-nodes-test', @@ -96,7 +92,24 @@ describe('CommunityNodeInfo - links & bugs URL', () => { }, }); - await waitFor(() => expect(getInstalledPackage).toHaveBeenCalled()); + await waitFor(() => expect(mockedFetchInstalledPackageInfo).toHaveBeenCalled()); + + expect(getByText('Package version 1.0.0 (Latest)')).toBeInTheDocument(); + }); + + it('displays "Latest" when only unverified update is available', async () => { + mockedFetchInstalledPackageInfo.mockResolvedValue({ + installedVersion: '1.0.0', + unverifiedUpdate: true, + } as ExtendedPublicInstalledPackage); + const { getByText } = createComponentRenderer(CommunityNodeFooter)({ + props: { + packageName: 'n8n-nodes-test', + showManage: false, + }, + }); + + await waitFor(() => expect(mockedFetchInstalledPackageInfo).toHaveBeenCalled()); expect(getByText('Package version 1.0.0 (Latest)')).toBeInTheDocument(); }); diff --git a/packages/frontend/editor-ui/src/components/Node/NodeCreator/Panel/CommunityNodeFooter.vue b/packages/frontend/editor-ui/src/components/Node/NodeCreator/Panel/CommunityNodeFooter.vue index 2a3d95091e..49e14f37ea 100644 --- a/packages/frontend/editor-ui/src/components/Node/NodeCreator/Panel/CommunityNodeFooter.vue +++ b/packages/frontend/editor-ui/src/components/Node/NodeCreator/Panel/CommunityNodeFooter.vue @@ -1,12 +1,11 @@ @@ -63,7 +62,9 @@ onMounted(async () => {
Package version {{ installedPackage.installedVersion }} ({{ - installedPackage.updateAvailable ? 'Legacy' : 'Latest' + installedPackage.updateAvailable && !installedPackage.unverifiedUpdate + ? 'Legacy' + : 'Latest' }})