Windows: Fixes #14903: Fix most Windows-specific test failures (#14904)

This commit is contained in:
Henry Heino
2026-03-27 12:17:12 +00:00
committed by GitHub
parent ee7362564c
commit 6cf9f1cc11
11 changed files with 54 additions and 29 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ const windowsPartitionLetter = __filename[0];
// /tmp/file.txt to {partition}:\tmp\file.txt
function platformPath(path: string) {
if (shim.isWindows()) {
return `${windowsPartitionLetter}:${path.replace(/\//g, '\\')}`;
return `${windowsPartitionLetter.toLowerCase()}:${path.replace(/\//g, '\\')}`;
} else {
return path;
}
+5 -1
View File
@@ -12,6 +12,9 @@ import ResourceService from '../../services/ResourceService';
import SearchEngine from '../search/SearchEngine';
const { MarkupToHtml } = require('@joplin/renderer');
import { NoteEntity, ResourceEntity } from '../database/types';
import { toFileProtocolPath } from '@joplin/utils/path';
import { join } from 'path';
import { htmlentities } from '@joplin/utils/html';
const createFolderForPagination = async (num: number, time: number) => {
await Folder.save({
@@ -512,10 +515,11 @@ describe('services/rest/Api', () => {
let response = null;
const f = await Folder.save({ title: 'pdf test1' });
const url = toFileProtocolPath(join(supportDir, 'welcome.pdf'));
response = await api.route(RequestMethod.POST, 'notes', null, JSON.stringify({
title: 'testing PDF embeds',
parent_id: f.id,
body_html: `<div> <embed src="file://${supportDir}/welcome.pdf" type="application/pdf" /> </div>`,
body_html: `<div> <embed src="${htmlentities(url)}" type="application/pdf" /> </div>`,
}));
const resources = await Resource.all();
+15 -2
View File
@@ -57,20 +57,33 @@ describe('urlUtils', () => {
[
'file:///home/builder/.config/joplindev-desktop/profile-owmhbsat/resources/4a12670298dd46abbb140ffc8a10b583.md',
'/home/builder/.config/joplindev-desktop/profile-owmhbsat/resources',
'posix',
{ itemId: '4a12670298dd46abbb140ffc8a10b583', hash: '' },
],
[
'file:///home/builder/.config/joplindev-desktop/profile-owmhbsat/resources/4a12670298dd46abbb140ffc8a10b583.md5#foo',
'/home/builder/.config/joplindev-desktop/profile-owmhbsat/resources',
'posix',
{ itemId: '4a12670298dd46abbb140ffc8a10b583', hash: 'foo' },
],
[
'file:///home/builder/.config/joplindev-desktop/profile-owmhbsat/resources/4a12670298dd46abbb140ffc8a10b583.png?t=12345',
'/home/builder/.config/joplindev-desktop/profile-owmhbsat/resources',
'posix',
{ itemId: '4a12670298dd46abbb140ffc8a10b583', hash: '' },
],
])('should detect resource file URLs', (url, resourceDir, expected) => {
expect(urlUtils.parseResourceUrl(urlUtils.fileUrlToResourceUrl(url, resourceDir))).toMatchObject(expected);
[
'file:///C:/Users/Test/.config/joplin-desktop/profile-owmhbsat/resources/a1234567890123456789012345678901.png?t=12345',
'C:\\Users\\Test\\.config\\joplin-desktop\\profile-owmhbsat\\resources',
'win32',
{ itemId: 'a1234567890123456789012345678901', hash: '' },
],
])('should detect resource file URLs (case %#)', (url, resourceDir, os, expected) => {
expect(
urlUtils.parseResourceUrl(
urlUtils.fileUrlToResourceUrl(url, resourceDir, os),
),
).toMatchObject(expected);
});
it('should extract resource URLs', (async () => {
+2 -2
View File
@@ -72,8 +72,8 @@ export const parseResourceUrl = (url: string) => {
};
};
export const fileUrlToResourceUrl = (fileUrl: string, resourceDir: string) => {
let resourceDirUrl = toFileProtocolPath(resourceDir);
export const fileUrlToResourceUrl = (fileUrl: string, resourceDir: string, os: string|null = null) => {
let resourceDirUrl = toFileProtocolPath(resourceDir, os);
if (!resourceDirUrl.endsWith('/')) {
resourceDirUrl += '/';
}
@@ -1,3 +1,4 @@
import { posix, win32 } from 'node:path';
import resolvePathWithinDir from './resolvePathWithinDir';
describe('resolvePathWithinDir', () => {
@@ -23,16 +24,16 @@ describe('resolvePathWithinDir', () => {
];
for (const testCase of testCases) {
expect(resolvePathWithinDir(testCase.baseDir, testCase.path, false)).toBe(testCase.expected);
expect(resolvePathWithinDir(testCase.baseDir, testCase.path, posix)).toBe(testCase.expected);
}
});
test('should return correct values for Windows-style paths', () => {
expect(resolvePathWithinDir('C:\\a\\test\\path', 'C:\\a\\test\\path\\2', true)).toBe('C:\\a\\test\\path\\2');
expect(resolvePathWithinDir('C:\\\\a\\test\\path', '.\\path\\2', true)).toBe('C:\\a\\test\\path\\path\\2');
expect(resolvePathWithinDir('C:\\a\\test\\path', '..\\path\\2', true)).toBe('C:\\a\\test\\path\\2');
expect(resolvePathWithinDir('C:\\a\\test\\path', '..\\2', true)).toBe(null);
expect(resolvePathWithinDir('D:\\a\\test\\path', 'C:\\a\\test\\path\\2', true)).toBe(null);
expect(resolvePathWithinDir('\\a\\test\\path', 'D:\\a\\test\\path\\2', true)).toBe(null);
expect(resolvePathWithinDir('C:\\a\\test\\path', 'C:\\a\\test\\path\\2', win32)).toBe('C:\\a\\test\\path\\2');
expect(resolvePathWithinDir('C:\\\\a\\test\\path', '.\\path\\2', win32)).toBe('C:\\a\\test\\path\\path\\2');
expect(resolvePathWithinDir('C:\\a\\test\\path', '..\\path\\2', win32)).toBe('C:\\a\\test\\path\\2');
expect(resolvePathWithinDir('C:\\a\\test\\path', '..\\2', win32)).toBe(null);
expect(resolvePathWithinDir('D:\\a\\test\\path', 'C:\\a\\test\\path\\2', win32)).toBe(null);
expect(resolvePathWithinDir('\\a\\test\\path', 'D:\\a\\test\\path\\2', win32)).toBe(null);
});
});
+1 -6
View File
@@ -12,13 +12,8 @@ const resolvePathWithinDir = (
baseDir: string, relativePath: string,
// For testing
forceWin32Paths?: boolean,
pathModule = path,
) => {
let pathModule = path;
if (forceWin32Paths === true) {
pathModule = path.win32;
}
let resolvedBaseDir = pathModule.resolve(baseDir);
const resolvedPath = pathModule.resolve(baseDir, relativePath);
+5 -1
View File
@@ -10,8 +10,12 @@ async function dbSchemaSnapshot(db: DbConnection): Promise<any> {
describe('db.migrations', () => {
let testIndex = 0;
beforeEach(async () => {
await beforeAllDb('db.migrations', { autoMigrate: false });
// Use `beforeAllDb` in `beforeEach` to ensure each test has its own database.
// To work around file locking issues on Windows, each test needs its own database instance:
const databaseKey = `db.migrations.${testIndex ++}`;
await beforeAllDb(databaseKey, { autoMigrate: false });
await beforeEachDb();
});
+11 -5
View File
@@ -21,8 +21,12 @@ const event2 = {
id: eventId2,
};
let testIndex = 0;
const beforeTest = async (envValues: Record<string, string> = null) => {
await beforeAllDb('db.replication', envValues ? { envValues } : null);
// Use `beforeAllDb` in `beforeEach` to ensure each test has its own database.
// To work around file locking issues on Windows, each test needs its own database instance:
const databaseKey = `db.replication.${testIndex ++}`;
await beforeAllDb(databaseKey, envValues ? { envValues } : null);
await beforeEachDb();
};
@@ -32,6 +36,10 @@ const afterTest = async () => {
describe('db.replication', () => {
afterEach(async () => {
await afterTest();
});
it('should reconnect a database', async () => {
if (getDatabaseClientType() === DatabaseConfigClient.PostgreSQL) return;
@@ -57,13 +65,13 @@ describe('db.replication', () => {
expect(results.length).toBe(2);
expect([results[0].id, results[1].id].sort()).toEqual([eventId1, eventId2]);
}
await afterTest();
});
it('should manually sync an SQLite slave instance', async () => {
if (getDatabaseClientType() === DatabaseConfigClient.PostgreSQL) return;
await beforeTest();
const masterConfig: DatabaseConfig = {
client: DatabaseConfigClient.SQLite,
name: `${packageRootDir}/db-master-test.sqlite`,
@@ -139,8 +147,6 @@ describe('db.replication', () => {
expect(result.items.length).toBe(1);
expect(result.items[0].type).toBe(ChangeType.Update);
await afterTest();
});
});
+1 -1
View File
@@ -29,7 +29,7 @@ describe('checkLibPaths', () => {
for (const testCase of testCases) {
const [expected, input] = testCase;
const actual = findInvalidImportPaths(__dirname, input.split('\n').map(l => l.trim()).join('\n'));
expect(actual.length).toBe(expected);
expect(actual).toHaveLength(expected);
}
});
+2 -1
View File
@@ -4,6 +4,7 @@ import { readFile } from 'fs-extra';
import { normalize } from 'path';
import yargs = require('yargs');
import { dirname } from './tool-utils';
import { toForwardSlashes } from '@joplin/utils/path';
export const findInvalidImportPaths = (baseDir: string, fileContent: string): string[] => {
const output: string[] = [];
@@ -26,7 +27,7 @@ export const findInvalidImportPaths = (baseDir: string, fileContent: string): st
const matches = regex.exec(fileContent);
if (!matches) break;
const [line, packagePath] = matches;
const fullPath = normalize(`${baseDir}/${packagePath}`);
const fullPath = toForwardSlashes(normalize(`${baseDir}/${packagePath}`));
if (fullPath.includes('packages/lib/') || fullPath.includes('packages/renderer/')) output.push(line);
}
+3 -2
View File
@@ -4,7 +4,7 @@ const path = require('path');
module.exports = {
resolveSnapshotPath: (testPath, snapshotExtension) => {
const srcPath = testPath
.replace(/dist\/src\//, 'src/')
.replace(/dist[/\\]src[/\\]/, 'src/')
.replace(/\.js$/, '');
const snapshotPath = path.join(
@@ -28,5 +28,6 @@ module.exports = {
return testPath;
},
testPathForConsistencyCheck: '/dist/src/example.test.js',
// Normalize to prevent assertion failures on Windows:
testPathForConsistencyCheck: path.normalize('/dist/src/example.test.js'),
};