mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-15 20:01:28 +00:00
Enhance file watching by ensuring 'node_modules' and '.git' are always ignored (#6391)
* Enhance file watching by ensuring 'node_modules' and '.git' are always ignored * fix: tests * rm: dialog assignments * fix: duplication
This commit is contained in:
@@ -85,7 +85,12 @@ class ApiSpecWatcher {
|
||||
this.watcherWorkspaces[watchPath] = workspacePath;
|
||||
}
|
||||
|
||||
const ignores = brunoConfig?.ignore || [];
|
||||
// Always ignore node_modules and .git, regardless of user config
|
||||
// This prevents infinite loops with symlinked directories (e.g., npm workspaces)
|
||||
const defaultIgnores = ['node_modules', '.git'];
|
||||
const userIgnores = brunoConfig?.ignore || [];
|
||||
const ignores = [...new Set([...defaultIgnores, ...userIgnores])];
|
||||
|
||||
const self = this;
|
||||
setTimeout(() => {
|
||||
const watcher = chokidar.watch(watchPath, {
|
||||
@@ -95,6 +100,12 @@ class ApiSpecWatcher {
|
||||
const normalizedPath = filepath.replace(/\\/g, '/');
|
||||
const relativePath = path.relative(watchPath, normalizedPath);
|
||||
|
||||
// Check if any path segment matches a default ignore pattern (handles symlinks)
|
||||
const pathSegments = relativePath.split(path.sep);
|
||||
if (pathSegments.some((segment) => defaultIgnores.includes(segment))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ignores.some((ignorePattern) => {
|
||||
const normalizedIgnorePattern = ignorePattern.replace(/\\/g, '/');
|
||||
return relativePath === normalizedIgnorePattern || relativePath.startsWith(normalizedIgnorePattern);
|
||||
|
||||
@@ -745,7 +745,12 @@ class CollectionWatcher {
|
||||
|
||||
this.startCollectionDiscovery(win, collectionUid);
|
||||
|
||||
const ignores = brunoConfig?.ignore || [];
|
||||
// Always ignore node_modules and .git, regardless of user config
|
||||
// This prevents infinite loops with symlinked directories (e.g., npm workspaces)
|
||||
const defaultIgnores = ['node_modules', '.git'];
|
||||
const userIgnores = brunoConfig?.ignore || [];
|
||||
const ignores = [...new Set([...defaultIgnores, ...userIgnores])];
|
||||
|
||||
setTimeout(() => {
|
||||
const watcher = chokidar.watch(watchPath, {
|
||||
ignoreInitial: false,
|
||||
@@ -754,6 +759,12 @@ class CollectionWatcher {
|
||||
const normalizedPath = normalizeAndResolvePath(filepath);
|
||||
const relativePath = path.relative(watchPath, normalizedPath);
|
||||
|
||||
// Check if any path segment matches a default ignore pattern (handles symlinks)
|
||||
const pathSegments = relativePath.split(path.sep);
|
||||
if (pathSegments.some((segment) => defaultIgnores.includes(segment))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ignores.some((ignorePattern) => {
|
||||
return relativePath === ignorePattern || relativePath.startsWith(ignorePattern);
|
||||
});
|
||||
|
||||
@@ -103,13 +103,11 @@ const openCollection = async (win, watcher, collectionPath, options = {}) => {
|
||||
let brunoConfig = await getCollectionConfigFile(collectionPath);
|
||||
const uid = generateUidBasedOnHash(collectionPath);
|
||||
|
||||
if (!brunoConfig.ignore || brunoConfig.ignore.length === 0) {
|
||||
// 5 Feb 2024:
|
||||
// bruno.json now supports an "ignore" field to specify which folders to ignore
|
||||
// if the ignore field is not present, we default to ignoring node_modules and .git
|
||||
// this is to maintain backwards compatibility with older collections
|
||||
brunoConfig.ignore = ['node_modules', '.git'];
|
||||
}
|
||||
// Always ensure node_modules and .git are ignored, regardless of user config
|
||||
// This prevents infinite loops with symlinked directories (e.g., npm workspaces)
|
||||
const defaultIgnores = ['node_modules', '.git'];
|
||||
const userIgnores = brunoConfig.ignore || [];
|
||||
brunoConfig.ignore = [...new Set([...defaultIgnores, ...userIgnores])];
|
||||
|
||||
// Transform the config to add existence checks for protobuf files and import paths
|
||||
brunoConfig = await transformBrunoConfigAfterRead(brunoConfig, collectionPath);
|
||||
|
||||
185
tests/collection/default-ignores/default-ignores.spec.ts
Normal file
185
tests/collection/default-ignores/default-ignores.spec.ts
Normal file
@@ -0,0 +1,185 @@
|
||||
import { test, expect } from '../../../playwright';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import { closeAllCollections, openCollectionAndAcceptSandbox } from '../../utils/page';
|
||||
import { buildCommonLocators } from '../../utils/page/locators';
|
||||
|
||||
test.describe('Default ignores for node_modules and .git', () => {
|
||||
test.afterEach(async ({ page }) => {
|
||||
await closeAllCollections(page);
|
||||
});
|
||||
|
||||
test('Should always ignore node_modules even when user has custom ignore config', async ({
|
||||
page,
|
||||
electronApp,
|
||||
createTmpDir
|
||||
}) => {
|
||||
const locators = buildCommonLocators(page);
|
||||
const collectionDir = await createTmpDir('node-modules-ignore-test');
|
||||
|
||||
// Create bruno.json with custom ignore that doesn't include node_modules
|
||||
const brunoConfig = {
|
||||
version: '1',
|
||||
name: 'Node Modules Ignore Test',
|
||||
type: 'collection',
|
||||
ignore: ['custom-folder', 'another-folder'] // Explicitly NOT including node_modules
|
||||
};
|
||||
fs.writeFileSync(path.join(collectionDir, 'bruno.json'), JSON.stringify(brunoConfig, null, 2));
|
||||
|
||||
// Create node_modules directory with .bru files inside
|
||||
const nodeModulesDir = path.join(collectionDir, 'node_modules');
|
||||
fs.mkdirSync(nodeModulesDir);
|
||||
fs.mkdirSync(path.join(nodeModulesDir, 'some-package'));
|
||||
|
||||
// Create a .bru file inside node_modules (should be ignored)
|
||||
fs.writeFileSync(
|
||||
path.join(nodeModulesDir, 'some-package', 'fake-request.bru'),
|
||||
`meta {
|
||||
name: Fake Request In Node Modules
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
get {
|
||||
url: https://fake.com
|
||||
body: none
|
||||
auth: none
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
// Create a real request at the collection root
|
||||
fs.writeFileSync(
|
||||
path.join(collectionDir, 'real-request.bru'),
|
||||
`meta {
|
||||
name: Real Request
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
get {
|
||||
url: https://real.com
|
||||
body: none
|
||||
auth: none
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
// Mock the electron dialog
|
||||
await electronApp.evaluate(
|
||||
({ dialog }, { collectionDir }) => {
|
||||
dialog.showOpenDialog = async () => ({
|
||||
canceled: false,
|
||||
filePaths: [collectionDir]
|
||||
});
|
||||
},
|
||||
{ collectionDir }
|
||||
);
|
||||
|
||||
// Open the collection
|
||||
await locators.plusMenu.button().click();
|
||||
await locators.dropdown.tippyItem('Open collection').click();
|
||||
|
||||
// Wait for collection to load
|
||||
await expect(locators.sidebar.collection('Node Modules Ignore Test')).toBeVisible({ timeout: 30000 });
|
||||
|
||||
// Accept the sandbox mode
|
||||
await openCollectionAndAcceptSandbox(page, 'Node Modules Ignore Test', 'safe');
|
||||
|
||||
// Verify only the real request is visible
|
||||
await expect(locators.sidebar.request('Real Request')).toBeVisible({ timeout: 10000 });
|
||||
|
||||
// The fake request inside node_modules should NOT be visible
|
||||
await expect(locators.sidebar.request('Fake Request In Node Modules')).not.toBeVisible();
|
||||
|
||||
// node_modules folder should not appear in the sidebar
|
||||
await expect(locators.sidebar.folder('node_modules')).not.toBeVisible();
|
||||
});
|
||||
|
||||
test('Should always ignore .git even when user has custom ignore config', async ({
|
||||
page,
|
||||
electronApp,
|
||||
createTmpDir
|
||||
}) => {
|
||||
const locators = buildCommonLocators(page);
|
||||
const collectionDir = await createTmpDir('git-ignore-test');
|
||||
|
||||
// Create bruno.json with custom ignore that doesn't include .git
|
||||
const brunoConfig = {
|
||||
version: '1',
|
||||
name: 'Git Ignore Test',
|
||||
type: 'collection',
|
||||
ignore: ['custom-folder'] // Explicitly NOT including .git
|
||||
};
|
||||
fs.writeFileSync(path.join(collectionDir, 'bruno.json'), JSON.stringify(brunoConfig, null, 2));
|
||||
|
||||
// Create .git directory with .bru files inside
|
||||
const gitDir = path.join(collectionDir, '.git');
|
||||
fs.mkdirSync(gitDir);
|
||||
fs.mkdirSync(path.join(gitDir, 'hooks'));
|
||||
|
||||
// Create a .bru file inside .git (should be ignored)
|
||||
fs.writeFileSync(
|
||||
path.join(gitDir, 'hooks', 'fake-git-request.bru'),
|
||||
`meta {
|
||||
name: Fake Request In Git
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
get {
|
||||
url: https://fake-git.com
|
||||
body: none
|
||||
auth: none
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
// Create a real request at the collection root
|
||||
fs.writeFileSync(
|
||||
path.join(collectionDir, 'real-request.bru'),
|
||||
`meta {
|
||||
name: Real Git Request
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
get {
|
||||
url: https://real.com
|
||||
body: none
|
||||
auth: none
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
// Mock the electron dialog
|
||||
await electronApp.evaluate(
|
||||
({ dialog }, { collectionDir }) => {
|
||||
dialog.showOpenDialog = async () => ({
|
||||
canceled: false,
|
||||
filePaths: [collectionDir]
|
||||
});
|
||||
},
|
||||
{ collectionDir }
|
||||
);
|
||||
|
||||
// Open the collection
|
||||
await locators.plusMenu.button().click();
|
||||
await locators.dropdown.tippyItem('Open collection').click();
|
||||
|
||||
// Wait for collection to load
|
||||
await expect(locators.sidebar.collection('Git Ignore Test')).toBeVisible({ timeout: 30000 });
|
||||
|
||||
// Accept the sandbox mode
|
||||
await openCollectionAndAcceptSandbox(page, 'Git Ignore Test', 'safe');
|
||||
|
||||
// Verify only the real request is visible
|
||||
await expect(locators.sidebar.request('Real Git Request')).toBeVisible({ timeout: 10000 });
|
||||
|
||||
// The fake request inside .git should NOT be visible
|
||||
await expect(locators.sidebar.request('Fake Request In Git')).not.toBeVisible();
|
||||
|
||||
// .git folder should not appear in the sidebar
|
||||
await expect(locators.sidebar.folder('.git')).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user