Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Run Tests

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: oven-sh/setup-bun@v1
with:
bun-version: 1.2.18

- name: Install dependencies
run: bun install --frozen

- name: Run tests
run: bun test --timeout 30000 --bail --coverage
5 changes: 1 addition & 4 deletions apps/web/client/messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,6 @@
"placeholder": "Escriba su mensaje...",
"tooltip": "Chatee con IA sobre el elemento seleccionado"
},
"mode": {
"tooltip": "Cambiar entre modos Construir y Preguntar"
},
"controls": {
"newChat": "Nuevo Chat",
"history": "Historial de Chat"
Expand Down Expand Up @@ -343,4 +340,4 @@
"shortcuts": "Atajos"
}
}
}
}
61 changes: 52 additions & 9 deletions apps/web/client/test/sandbox/sandbox.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { IGNORED_DIRECTORIES, JSX_FILE_EXTENSIONS } from '@onlook/constants';
import { afterEach, beforeEach, describe, expect, mock, test } from 'bun:test';
import { runInAction } from 'mobx';

// Setup mocks before imports
// Mock localforage before importing anything that uses it
Expand All @@ -19,6 +20,7 @@ describe('SandboxManager', () => {
let mockSession: any;
let mockWatcher: any;
let mockFileSync: any;
let mockEditorEngine: any;

beforeEach(() => {
mockGetItem.mockClear();
Expand Down Expand Up @@ -64,6 +66,7 @@ describe('SandboxManager', () => {
// Create a sandbox with a mock FileSyncManager
mockFileSync = {
readOrFetch: mock(async () => '<div>Mocked Content</div>'),
readOrFetchBatch: mock(async () => []),
write: mock(async () => true),
clear: mock(async () => undefined),
updateCache: mock(async () => undefined),
Expand Down Expand Up @@ -98,9 +101,13 @@ describe('SandboxManager', () => {
}),
watch: mock(async () => mockWatcher),
},
disconnect: mock(async () => undefined),
};

sandboxManager = new SandboxManager();
mockEditorEngine = {
};

sandboxManager = new SandboxManager(mockEditorEngine);
});

afterEach(() => {
Expand All @@ -127,10 +134,15 @@ describe('SandboxManager', () => {
writeTextFile: mock(async () => true),
watch: mock(async () => mockWatcher),
},
disconnect: mock(async () => undefined),
};

const testManager = new SandboxManager();
testManager.init(testMockSession);
const testManager = new SandboxManager(mockEditorEngine);

runInAction(() => {
// @ts-ignore - accessing private property for testing
testManager.session.session = testMockSession;
});

const files = await testManager.listFilesRecursively(
'./',
Expand All @@ -146,6 +158,12 @@ describe('SandboxManager', () => {
});

test('should read file content', async () => {
// Set up session for this test
runInAction(() => {
// @ts-ignore - accessing private property for testing
sandboxManager.session.session = mockSession;
});

// Override the fileSync property to use our specific mock
// @ts-ignore - accessing private property for testing
sandboxManager.fileSync = mockFileSync;
Expand All @@ -156,6 +174,12 @@ describe('SandboxManager', () => {
});

test('should write file content', async () => {
// Set up session for this test
runInAction(() => {
// @ts-ignore - accessing private property for testing
sandboxManager.session.session = mockSession;
});

// Override the fileSync property to use our specific mock
// @ts-ignore - accessing private property for testing
sandboxManager.fileSync = mockFileSync;
Expand All @@ -167,12 +191,18 @@ describe('SandboxManager', () => {
expect(result).toBe(true);
expect(mockFileSync.write).toHaveBeenCalledWith(
'file1.tsx',
'<div id="123">Modified Component</div>',
'<div id="123">Modified Component</div>;\n',
expect.any(Function),
);
});

test('should read from localforage cache when reading files multiple times', async () => {
// Set up session for this test
runInAction(() => {
// @ts-ignore - accessing private property for testing
sandboxManager.session.session = mockSession;
});

// First read gets from filesystem and caches
await sandboxManager.readFile('file1.tsx');

Expand All @@ -181,7 +211,7 @@ describe('SandboxManager', () => {

// Second read should use cache
const content2 = await sandboxManager.readFile('file1.tsx');
expect(content2).toBe('<div>Test Component</div>');
expect(content2.content).toBe('<div>Test Component</div>');

// Filesystem should not be accessed for the second read
expect(mockSession.fs.readTextFile).not.toHaveBeenCalled();
Expand All @@ -200,14 +230,15 @@ describe('SandboxManager', () => {
readdir: mock(async () => []),
watch: mock(async () => mockWatcher),
},
disconnect: mock(async () => undefined),
};

const errorManager = new SandboxManager();
errorManager.init(errorSession);
const errorManager = new SandboxManager(mockEditorEngine);

// We need to create a custom fileSync mock that returns null for this test
const errorFileSync = {
readOrFetch: mock(async () => null),
readOrFetchBatch: mock(async () => []),
write: mock(async () => false),
clear: mock(async () => undefined),
updateCache: mock(async () => undefined),
Expand All @@ -226,7 +257,7 @@ describe('SandboxManager', () => {
expect(writeResult).toBe(false);
expect(errorFileSync.write).toHaveBeenCalledWith(
'error.tsx',
'<div>Content</div>',
'<div>Content</div>;\n',
expect.any(Function),
);
});
Expand Down Expand Up @@ -303,6 +334,12 @@ describe('SandboxManager', () => {
});

test('should normalize file paths for read', async () => {
// Set up session for this test
runInAction(() => {
// @ts-ignore - accessing private property for testing
sandboxManager.session.session = mockSession;
});

// Override the fileSync property in the sandboxManager
// @ts-ignore - accessing private property for testing
sandboxManager.fileSync = mockFileSync;
Expand All @@ -327,6 +364,12 @@ describe('SandboxManager', () => {
});

test('should normalize file paths for write', async () => {
// Set up session for this test
runInAction(() => {
// @ts-ignore - accessing private property for testing
sandboxManager.session.session = mockSession;
});

// Override the fileSync property in the sandboxManager
// @ts-ignore - accessing private property for testing
sandboxManager.fileSync = mockFileSync;
Expand All @@ -345,7 +388,7 @@ describe('SandboxManager', () => {
await sandboxManager.writeFile(variant, 'test');
expect(mockFileSync.write).toHaveBeenCalledWith(
normalizedPath,
'test',
'test;\n',
expect.any(Function),
);
}
Expand Down
Binary file modified bun.lockb
Binary file not shown.
2 changes: 2 additions & 0 deletions packages/constants/src/files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export const IGNORED_UPLOAD_DIRECTORIES = [...BASE_EXCLUDED_DIRECTORIES, CUSTOM_

export const EXCLUDED_PUBLISH_DIRECTORIES = [...BASE_EXCLUDED_DIRECTORIES, 'coverage'];

export const IGNORED_DIRECTORIES = ['api', 'components', 'lib', 'utils', 'node_modules'];

export const JSX_FILE_EXTENSIONS = ['.jsx', '.tsx'];

export const JS_FILE_EXTENSIONS = ['.js', '.ts', '.mjs', '.cjs'];
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading