Skip to content

Commit cad086b

Browse files
nadr0franknoirotgithub-actions[bot]jacebrowning
authored
feature: Project Explorer update, first pass. (#7656)
* chore: saving off skeleton progress... need to write unit tests do some clean up * chore: big cleanup, typing, adding comments, better structure * chore: moved selected row and opened rows up a level in the react components * feature: button to collapse all folders * feat: implemented projet explorer refresh * feat: sort was not sorting folders and files at each level, selection logic was not taking parent into account * chore: unable to implement insert at index, need to come back to this, wasting time * chore: css pointer and hover * chore: adding custom folder icon * chore: adding opened icon * feat: adding line for indentation visual * fix: react key warning * fix: trying to make progress on selection, active index, keyboard, and moust events * chore: aria support * chore: implementing removing the click area when you click outside the ref * fix: fmt? * chore: active index logic, keyboard arrow logic * chore: outline offset logic * chore: some arrow key usage, need to move data up a level I think * chore: more data up a level * fix: improving file/folder structure and resolving typescript errors * chore: clean up * fix: fmt * fix: hmm trying to deal with state management * fix: moving the filter logic up * chore: keyboard interactions * fix: ope * fix:commiting broken context menu * fix: some testing code for dragging * chore:debug with react dev tools * fix: dang * fix: context menu selection outline * fix: fmt * fix: moved path into the file entry * fix: saving off renaming progress * fix: fmt * chore: saving off some progress for the renaming, need a new systemiomachine actor * fix: renaming folders! * fix: blocking arrow keys on renaming * chore: renaming files with the systemio * fix: force renaming with extensions since they can rename their file out of view :( * fix: deleting file or folder * fix: deleting folders * fix: open in new window * fix: fixing linter and ts issues * fix: more tsc error fixing * fix: renaming handlers * fix: on context menu open * fix: more ts fixes * fix: more tsc fixes * fix: need to fix some major event typescript handling * fix: testing with multiples! * fix: handling blur,focus for the containers to start tabbing and using arrow keys * fix: updating icons * fix: placeholders and showing them for add file or foldeR * fix: big add file and folder logic * fix: fmt * fix: implemented adding files and folders at the activeIndex level instead of selected * chore: css fixes based on Frank's design * chore: more css updates * chore: css to know what region you are renaming or adding a new file in * chore: improving some css and layout issues * fix: the caching of the callback from the context menu borked the function * chore: trying to layout the project explorer in the tab properly * fix: proxy header actions * fix: clear internal state across projects switching * fix: ope, opening any file known to man! * fix: only running on kcl files and fmt * fix: parent path shows error * fix: fmt * chore: opening parent folders all the way down to the file that is loaded via the index loader data project,file * fix: error handling missing file scenario * fix: getting rid of debug index * chore: placeholder is empty string so the fake name is not shown to the user * fix: keep placeholder if it is a real file, only hide it on the fake placeholder file and folder * fix: auto fmt * chore: improved copy for renaming folders * chore: updated and tested copy for renaming file names * chore: updated copy for creating a blank kcl file * chore: fixed copy for creating a blank folder: * chore: redirect to file after creation * chore: redirect on rename file at any tree level * fix: auto fmt * fix: only navigate on rename if the file you are renaming is the one you have loaded * fix: redirect only on rename, need to have a cleaner path library and variable name * fix: fmt * fix: adding comments * fix: delete and navigate * fix: fmt * fix: on enter it opens file * fix: removing debug package * fix: fixing tsc errors * fix: resolving tsc errors * fix: fixing bug with enter with project loader name ref * fix: fixing height to allow clicking empty space then the arrow keys for -1 indexing * fix: ope testing code when helping adam got here * fix: adding toast since it is using a create file and navigate function which is awkwardly named import file url * fix: typo * fix: trying to fix more tsc errors * chore: readonly and navigation booleans * fix: aria set size and position in set were computed wrong * chore: deleted the old file tree: * chore: filemachineprovider still has useful code, it is now modelingpageprovider * fix: formatter * fix: adding some unit tests * chore: adding unit tests for adding the placeholders * fix: 2 e2e tests, made a new helper function for the future * fix: fixing another e2e test * fix: finally found the right helper function, don't know why this is a toolbar, it is not a toolbar * fix: e2e tests... * fix: updating button role to the treeitem * fix: fixing e2e test * ope: I need the delete confirmation * fix: local state for modal confirmation but the action takes place on the callback of the modal in the parent * fix: fixing more e2e tests * fix: fixing more e2e tests * chore: added insert on importable files * fix: fmt * fix: fixing another e2e test * fix: fixing locator for another e2e test * fix: another e2e test * fix: I thought I fixed this typo already * fix: make ENOENT a warning, it isn't a real error * fix: last known index so you can swap file/folder when creating in the same location * fix: fixing another locator for e2e test * chore: Jest to vitestga! * fix: this is covered in the unit test runner * fix: cleanup testing code * Fix tsc errors * fix: moved file so the url is found * fix: ope, wrong function * fix: addressing PR comments, implementing close folder if you are on first file and press left arrow * chore: learning and implementing unit component testing, got some good ones for ProjectExplorer! * chore: adding more ProjectExplorer tests, added an event click test! it works! * chore: adding a unit test for clicking collapse button in ProjectExplorer * chore: adding more unit test scenarios I manually tested but now in react unit tests * chore: added unit test for opening and closing folders to check child folders stay opened if a higher parent is closed and reponed * fix: removed unused call from makefile * fix: I swapped a boolean statement for navigation, will navigate on file create if you have canNavigate enabled * Update snapshots * Update snapshots * Update snapshots * fix: adding an issue todo for cut,copy, and paste * Update snapshots * fix: don't use a real url in the tests? * fix: trying to remove this testing url --------- Co-authored-by: Frank Noirot <[email protected]> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Jace Browning <[email protected]>
1 parent 8108393 commit cad086b

37 files changed

+3676
-1619
lines changed

.github/workflows/unit-tests.yml

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -97,48 +97,3 @@ jobs:
9797
git commit -am "Look at this (photo)Graph *in the voice of Nickelback*" || true
9898
git push
9999
git push origin ${{ github.head_ref }}
100-
101-
npm-test-unit-components:
102-
runs-on: namespace-profile-ubuntu-2-cores
103-
needs: npm-build-wasm
104-
steps:
105-
- uses: actions/checkout@v4
106-
107-
- uses: actions/setup-node@v4
108-
with:
109-
node-version-file: '.nvmrc'
110-
cache: 'npm'
111-
112-
- run: npm install
113-
- uses: taiki-e/install-action@c07504cae06f832dc8de08911c9a9c5cddb0d2d3
114-
with:
115-
tool: wasm-pack
116-
117-
- name: Download all artifacts
118-
uses: actions/download-artifact@v4
119-
120-
- name: Copy prepared wasm
121-
run: |
122-
ls -R prepared-wasm
123-
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
124-
mkdir rust/kcl-wasm-lib/pkg
125-
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
126-
127-
- name: Copy prepared ts-rs bindings
128-
run: |
129-
ls -R prepared-ts-rs-bindings
130-
mkdir rust/kcl-lib/bindings
131-
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
132-
133-
- name: Run component tests
134-
run: npm run test:unit:components
135-
136-
- name: Upload results
137-
if: always()
138-
run: .github/ci-cd-scripts/upload-results.sh
139-
env:
140-
TAB_API_URL: ${{ secrets.TAB_API_URL }}
141-
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
142-
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
143-
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
144-
CI_SUITE: unit:components

Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,6 @@ test: test-unit test-e2e
129129
.PHONY: test-unit
130130
test-unit: install ## Run the unit tests
131131
npm run test:rust
132-
npm run test:unit:components
133132
@ curl -fs localhost:3000 >/dev/null || ( echo "Error: localhost:3000 not available, 'make run-web' first" && exit 1 )
134133
npm run test:unit
135134

e2e/playwright/desktop-export.spec.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
1111
test(
1212
'export works on the first try',
1313
{ tag: ['@desktop', '@macos', '@windows', '@skipLocalEngine'] },
14-
async ({ page, context, scene, tronApp, cmdBar }, testInfo) => {
14+
async ({ page, context, scene, tronApp, cmdBar, toolbar }, testInfo) => {
1515
if (!tronApp) {
1616
fail()
1717
}
@@ -95,8 +95,7 @@ test(
9595
await u.openFilePanel()
9696

9797
// Click on the other file
98-
const otherKclButton = page.getByRole('button', { name: 'other.kcl' })
99-
await otherKclButton.click()
98+
await toolbar.openFile('other.kcl')
10099

101100
// Close the file pane
102101
await u.closeFilePanel()

e2e/playwright/file-tree.spec.ts

Lines changed: 23 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ test.describe('when using the file tree to', () => {
267267
{
268268
tag: '@desktop',
269269
},
270-
async ({ page }, testInfo) => {
270+
async ({ page, toolbar }, testInfo) => {
271271
const {
272272
panesOpen,
273273
pasteCodeInEditor,
@@ -293,19 +293,11 @@ test.describe('when using the file tree to', () => {
293293

294294
// Create a large lego file
295295
await createNewFile('lego')
296-
const legoFile = page.getByRole('listitem').filter({
297-
has: page.getByRole('button', { name: 'lego.kcl' }),
298-
})
299-
await expect(legoFile).toBeVisible({ timeout: 60_000 })
300-
await legoFile.click()
301296
const kclLego = await fsp.readFile(
302297
'rust/kcl-lib/e2e/executor/inputs/lego.kcl',
303298
'utf-8'
304299
)
305300
await pasteCodeInEditor(kclLego)
306-
const mainFile = page.getByRole('listitem').filter({
307-
has: page.getByRole('button', { name: 'main.kcl' }),
308-
})
309301

310302
// Open settings and enable the debug panel
311303
await page
@@ -319,12 +311,12 @@ test.describe('when using the file tree to', () => {
319311
await test.step('swap between small and large files', async () => {
320312
await openDebugPanel()
321313
// Previously created a file so we need to start back at main.kcl
322-
await mainFile.click()
314+
await toolbar.openFile('main.kcl')
323315
await expectCmdLog('[data-message-type="execution-done"]', 60_000)
324316
// Click the large file
325-
await legoFile.click()
317+
await toolbar.openFile('lego.kcl')
326318
// Once it is building, click back to the smaller file
327-
await mainFile.click()
319+
await toolbar.openFile('main.kcl')
328320
await expectCmdLog('[data-message-type="execution-done"]', 60_000)
329321
await closeDebugPanel()
330322
})
@@ -364,13 +356,8 @@ test.describe('Renaming in the file tree', () => {
364356
const filePath = join(dir, 'Test Project', `${newFileName}.kcl`)
365357
return fs.existsSync(filePath)
366358
}
367-
368-
const fileToRename = page
369-
.getByRole('listitem')
370-
.filter({ has: page.getByRole('button', { name: 'fileToRename.kcl' }) })
371-
const renamedFile = page
372-
.getByRole('listitem')
373-
.filter({ has: page.getByRole('button', { name: 'newFileName.kcl' }) })
359+
const fileToRename = u.locatorFile('fileToRename.kcl')
360+
const renamedFile = u.locatorFile('newFileName.kcl')
374361
const renameMenuItem = page.getByRole('button', { name: 'Rename' })
375362
const renameInput = page.getByPlaceholder('fileToRename.kcl')
376363
const codeLocator = page.locator('.cm-content')
@@ -453,12 +440,8 @@ test.describe('Renaming in the file tree', () => {
453440
}
454441
const projectLink = page.getByText('Test Project')
455442
const projectMenuButton = page.getByTestId('project-sidebar-toggle')
456-
const fileToRename = page
457-
.getByRole('listitem')
458-
.filter({ has: page.getByRole('button', { name: 'fileToRename.kcl' }) })
459-
const renamedFile = page.getByRole('listitem').filter({
460-
has: page.getByRole('button', { name: newFileName + FILE_EXT }),
461-
})
443+
const fileToRename = u.locatorFile('fileToRename.kcl')
444+
const renamedFile = u.locatorFile(newFileName + FILE_EXT)
462445
const renameMenuItem = page.getByRole('button', { name: 'Rename' })
463446
const renameInput = page.getByPlaceholder('fileToRename.kcl')
464447
const codeLocator = page.locator('.cm-content')
@@ -534,10 +517,8 @@ test.describe('Renaming in the file tree', () => {
534517
// Constants and locators
535518
const projectLink = page.getByText('Test Project')
536519
const projectMenuButton = page.getByTestId('project-sidebar-toggle')
537-
const folderToRename = page.getByRole('button', {
538-
name: 'folderToRename',
539-
})
540-
const renamedFolder = page.getByRole('button', { name: 'newFolderName' })
520+
const folderToRename = u.locatorFolder('folderToRename')
521+
const renamedFolder = u.locatorFolder('newFolderName')
541522
const renameMenuItem = page.getByRole('button', { name: 'Rename' })
542523
const originalFolderName = 'folderToRename'
543524
const renameInput = page.getByPlaceholder(originalFolderName)
@@ -616,13 +597,9 @@ test.describe('Renaming in the file tree', () => {
616597
// Constants and locators
617598
const projectLink = page.getByText('Test Project')
618599
const projectMenuButton = page.getByTestId('project-sidebar-toggle')
619-
const folderToRename = page.getByRole('button', {
620-
name: 'folderToRename',
621-
})
622-
const renamedFolder = page.getByRole('button', { name: 'newFolderName' })
623-
const fileWithinFolder = page.getByRole('listitem').filter({
624-
has: page.getByRole('button', { name: 'someFileWithin.kcl' }),
625-
})
600+
const folderToRename = u.locatorFolder('folderToRename')
601+
const renamedFolder = u.locatorFolder('newFolderName')
602+
const fileWithinFolder = u.locatorFile('someFileWithin.kcl')
626603
const renameMenuItem = page.getByRole('button', { name: 'Rename' })
627604
const originalFolderName = 'folderToRename'
628605
const renameInput = page.getByPlaceholder(originalFolderName)
@@ -716,9 +693,7 @@ test.describe('Deleting items from the file pane', () => {
716693
// Constants and locators
717694
const projectCard = page.getByText('testProject')
718695
const projectMenuButton = page.getByTestId('project-sidebar-toggle')
719-
const fileToDelete = page
720-
.getByRole('listitem')
721-
.filter({ has: page.getByRole('button', { name: 'fileToDelete.kcl' }) })
696+
const fileToDelete = u.locatorFile('fileToDelete.kcl')
722697
const deleteMenuItem = page.getByRole('button', { name: 'Delete' })
723698
const deleteConfirmation = page.getByTestId('delete-confirmation')
724699

@@ -783,9 +758,7 @@ test.describe('Deleting items from the file pane', () => {
783758
// Constants and locators
784759
const projectCard = page.getByText('Test Project')
785760
const projectMenuButton = page.getByTestId('project-sidebar-toggle')
786-
const folderToDelete = page.getByRole('button', {
787-
name: 'folderToDelete',
788-
})
761+
const folderToDelete = u.locatorFolder('folderToDelete')
789762
const deleteMenuItem = page.getByRole('button', { name: 'Delete' })
790763
const deleteConfirmation = page.getByTestId('delete-confirmation')
791764

@@ -837,12 +810,8 @@ test.describe('Deleting items from the file pane', () => {
837810
// Constants and locators
838811
const projectCard = page.getByText('Test Project')
839812
const projectMenuButton = page.getByTestId('project-sidebar-toggle')
840-
const folderToDelete = page.getByRole('button', {
841-
name: 'folderToDelete',
842-
})
843-
const fileWithinFolder = page.getByRole('listitem').filter({
844-
has: page.getByRole('button', { name: 'someFileWithin.kcl' }),
845-
})
813+
const folderToDelete = u.locatorFolder('folderToDelete')
814+
const fileWithinFolder = u.locatorFile('someFileWithin.kcl')
846815
const deleteMenuItem = page.getByRole('button', { name: 'Delete' })
847816
const deleteConfirmation = page.getByTestId('delete-confirmation')
848817

@@ -905,12 +874,8 @@ test.describe('Deleting items from the file pane', () => {
905874
// Constants and locators
906875
const projectCard = page.getByText(TEST_PROJECT_NAME)
907876
const projectMenuButton = page.getByTestId('project-sidebar-toggle')
908-
const folderToDelete = page.getByRole('button', {
909-
name: 'folderToDelete',
910-
})
911-
const fileWithinFolder = page.getByRole('listitem').filter({
912-
has: page.getByRole('button', { name: 'someFileWithin.kcl' }),
913-
})
877+
const folderToDelete = u.locatorFolder('folderToDelete')
878+
const fileWithinFolder = u.locatorFile('someFileWithin.kcl')
914879

915880
await test.step('Open project and navigate into folderToDelete', async () => {
916881
await projectCard.click()
@@ -969,12 +934,8 @@ test.describe('Deleting items from the file pane', () => {
969934
// Constants and locators
970935
const projectCard = page.getByText(TEST_PROJECT_NAME)
971936
const projectMenuButton = page.getByTestId('project-sidebar-toggle')
972-
const folderToDelete = page.getByRole('button', {
973-
name: 'folderToDelete',
974-
})
975-
const fileWithinFolder = page.getByRole('listitem').filter({
976-
has: page.getByRole('button', { name: 'someFileWithin.kcl' }),
977-
})
937+
const folderToDelete = u.locatorFolder('folderToDelete')
938+
const fileWithinFolder = u.locatorFile('someFileWithin.kcl')
978939

979940
await test.step('Open project and navigate into folderToDelete', async () => {
980941
await projectCard.click()
@@ -1039,9 +1000,7 @@ test.describe('Undo and redo do not keep history when navigating between files',
10391000

10401001
// Constants and locators
10411002
const projectCard = page.getByText('testProject')
1042-
const otherFile = page
1043-
.getByRole('listitem')
1044-
.filter({ has: page.getByRole('button', { name: 'other.kcl' }) })
1003+
const otherFile = u.locatorFile('other.kcl')
10451004

10461005
await test.step('Open project and make a change to the file', async () => {
10471006
await projectCard.click()
@@ -1106,9 +1065,7 @@ test.describe('Undo and redo do not keep history when navigating between files',
11061065

11071066
// Constants and locators
11081067
const projectCard = page.getByText('testProject')
1109-
const otherFile = page
1110-
.getByRole('listitem')
1111-
.filter({ has: page.getByRole('button', { name: 'other.kcl' }) })
1068+
const otherFile = u.locatorFile('other.kcl')
11121069

11131070
const badContent = 'this shit'
11141071
await test.step('Open project and make a change to the file', async () => {

e2e/playwright/fixtures/toolbarFixture.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export class ToolbarFixture {
7676
this.exitSketchBtn = page.getByTestId('sketch-exit')
7777
this.fileTreeBtn = page.locator('[id="files-button-holder"]')
7878
this.createFileBtn = page.getByTestId('create-file-button')
79-
this.treeInputField = page.getByTestId('tree-input-field')
79+
this.treeInputField = page.getByTestId('file-rename-field')
8080
this.loadButton = page.getByTestId('add-file-to-project-pane-button')
8181

8282
this.filePane = page.locator('#files-pane')

e2e/playwright/projects.spec.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,7 @@ default project name`, async ({ homePage, toolbar }) => {
873873
test(
874874
'File in the file pane should open with a single click',
875875
{ tag: '@desktop' },
876-
async ({ context, homePage, page }, testInfo) => {
876+
async ({ context, homePage, page, scene, toolbar }, testInfo) => {
877877
const projectName = 'router-template-slate'
878878
await context.folderSetupFn(async (dir) => {
879879
await fsp.mkdir(`${dir}/${projectName}`, { recursive: true })
@@ -900,11 +900,7 @@ test(
900900
await expect(u.codeLocator).toContainText('minClampingDistance')
901901

902902
await page.getByRole('button', { name: 'Project Files' }).click()
903-
904-
const file = page.getByRole('button', { name: 'otherThingToClickOn.kcl' })
905-
await expect(file).toBeVisible()
906-
907-
await file.click()
903+
await toolbar.openFile('otherThingToClickOn.kcl')
908904

909905
await expect(u.codeLocator).toContainText(
910906
'A mounting bracket for the Focusrite Scarlett Solo audio interface'
@@ -1532,7 +1528,8 @@ test(
15321528
})
15331529

15341530
await test.step('check the last file is out of view initially, and can be scrolled to', async () => {
1535-
const element = page.getByText('tangential_arc.kcl')
1531+
const u = await getUtils(page)
1532+
const element = u.locatorFile('tangential_arc.kcl')
15361533
const container = page.getByTestId('file-pane-scroll-container')
15371534

15381535
await expect(await isOutOfViewInScrollContainer(element, container)).toBe(

0 commit comments

Comments
 (0)