Fix reading files from WebAssembly (#4183)
This commit is contained in:
@ -1,6 +1,16 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
import fsp from 'fs/promises'
|
||||
import { uuidv4 } from 'lib/utils'
|
||||
import { getUtils, setup, tearDown } from './test-utils'
|
||||
import {
|
||||
darkModeBgColor,
|
||||
darkModePlaneColorXZ,
|
||||
executorInputPath,
|
||||
getUtils,
|
||||
setup,
|
||||
setupElectron,
|
||||
tearDown,
|
||||
} from './test-utils'
|
||||
import { join } from 'path'
|
||||
|
||||
test.beforeEach(async ({ context, page }, testInfo) => {
|
||||
await setup(context, page, testInfo)
|
||||
@ -974,4 +984,84 @@ test.describe('Editor tests', () => {
|
||||
|> close(%)
|
||||
|> extrude(5, %)`)
|
||||
})
|
||||
|
||||
test(
|
||||
`Can use the import stdlib function on a local OBJ file`,
|
||||
{ tag: '@electron' },
|
||||
async ({ browserName }, testInfo) => {
|
||||
const { electronApp, page } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
const bracketDir = join(dir, 'cube')
|
||||
await fsp.mkdir(bracketDir, { recursive: true })
|
||||
await fsp.copyFile(
|
||||
executorInputPath('cube.obj'),
|
||||
join(bracketDir, 'cube.obj')
|
||||
)
|
||||
await fsp.writeFile(join(bracketDir, 'main.kcl'), '')
|
||||
},
|
||||
})
|
||||
const viewportSize = { width: 1200, height: 500 }
|
||||
await page.setViewportSize(viewportSize)
|
||||
|
||||
// Locators and constants
|
||||
const u = await getUtils(page)
|
||||
const projectLink = page.getByRole('link', { name: 'cube' })
|
||||
const gizmo = page.locator('[aria-label*=gizmo]')
|
||||
const resetCameraButton = page.getByRole('button', { name: 'Reset view' })
|
||||
const locationToHavColor = async (
|
||||
position: { x: number; y: number },
|
||||
color: [number, number, number]
|
||||
) => {
|
||||
return u.getGreatestPixDiff(position, color)
|
||||
}
|
||||
const notTheOrigin = {
|
||||
x: viewportSize.width * 0.55,
|
||||
y: viewportSize.height * 0.3,
|
||||
}
|
||||
const origin = { x: viewportSize.width / 2, y: viewportSize.height / 2 }
|
||||
const errorIndicators = page.locator('.cm-lint-marker-error')
|
||||
|
||||
await test.step(`Open the empty file, see the default planes`, async () => {
|
||||
await projectLink.click()
|
||||
await u.waitForPageLoad()
|
||||
await expect
|
||||
.poll(
|
||||
async () => locationToHavColor(notTheOrigin, darkModePlaneColorXZ),
|
||||
{
|
||||
timeout: 5000,
|
||||
message: 'XZ plane color is visible',
|
||||
}
|
||||
)
|
||||
.toBeLessThan(15)
|
||||
})
|
||||
await test.step(`Write the import function line`, async () => {
|
||||
await u.codeLocator.fill(`import('cube.obj')`)
|
||||
await page.waitForTimeout(800)
|
||||
})
|
||||
await test.step(`Reset the camera before checking`, async () => {
|
||||
await u.doAndWaitForCmd(async () => {
|
||||
await gizmo.click({ button: 'right' })
|
||||
await resetCameraButton.click()
|
||||
}, 'zoom_to_fit')
|
||||
})
|
||||
await test.step(`Verify that we see the imported geometry and no errors`, async () => {
|
||||
await expect(errorIndicators).toHaveCount(0)
|
||||
await expect
|
||||
.poll(async () => locationToHavColor(origin, darkModePlaneColorXZ), {
|
||||
timeout: 3000,
|
||||
message: 'Plane color should not be visible',
|
||||
})
|
||||
.toBeGreaterThan(15)
|
||||
await expect
|
||||
.poll(async () => locationToHavColor(origin, darkModeBgColor), {
|
||||
timeout: 3000,
|
||||
message: 'Background color should not be visible',
|
||||
})
|
||||
.toBeGreaterThan(15)
|
||||
})
|
||||
|
||||
await electronApp.close()
|
||||
}
|
||||
)
|
||||
})
|
||||
|
@ -47,6 +47,14 @@ export const commonPoints = {
|
||||
num2: 14.44,
|
||||
}
|
||||
|
||||
/** A semi-reliable color to check the default XZ plane on
|
||||
* in dark mode in the default camera position
|
||||
*/
|
||||
export const darkModePlaneColorXZ: [number, number, number] = [50, 50, 99]
|
||||
|
||||
/** A semi-reliable color to check the default dark mode bg color against */
|
||||
export const darkModeBgColor: [number, number, number] = [27, 27, 27]
|
||||
|
||||
export const editorSelector = '[role="textbox"][data-language="kcl"]'
|
||||
type PaneId = 'variables' | 'code' | 'files' | 'logs'
|
||||
|
||||
|
2
interface.d.ts
vendored
2
interface.d.ts
vendored
@ -23,8 +23,8 @@ export interface IElectronAPI {
|
||||
key: string,
|
||||
callback: (eventType: string, path: string) => void
|
||||
) => void
|
||||
readFile: typeof fs.readFile
|
||||
watchFileOff: (path: string, key: string) => void
|
||||
readFile: (path: string) => ReturnType<fs.readFile>
|
||||
writeFile: (
|
||||
path: string,
|
||||
data: string | Uint8Array
|
||||
|
@ -140,7 +140,7 @@ const FileTreeItem = ({
|
||||
async (eventType, path) => {
|
||||
// Don't try to read a file that was removed.
|
||||
if (isCurrentFile && eventType !== 'unlink') {
|
||||
let code = await window.electron.readFile(path)
|
||||
let code = await window.electron.readFile(path, { encoding: 'utf-8' })
|
||||
code = normalizeLineEndings(code)
|
||||
codeManager.updateCodeStateEditor(code)
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ class FileSystemManager {
|
||||
return Promise.resolve(window.electron.path.join(dir, path))
|
||||
}
|
||||
|
||||
async readFile(path: string): Promise<Uint8Array | void> {
|
||||
async readFile(path: string): Promise<Uint8Array> {
|
||||
// Using local file system only works from desktop.
|
||||
if (!isDesktop()) {
|
||||
return Promise.reject(
|
||||
|
@ -448,7 +448,9 @@ export const readProjectSettingsFile = async (
|
||||
}
|
||||
}
|
||||
|
||||
const configToml = await window.electron.readFile(settingsPath)
|
||||
const configToml = await window.electron.readFile(settingsPath, {
|
||||
encoding: 'utf-8',
|
||||
})
|
||||
const configObj = parseProjectSettings(configToml)
|
||||
if (err(configObj)) {
|
||||
return Promise.reject(configObj)
|
||||
@ -467,7 +469,9 @@ export const readAppSettingsFile = async () => {
|
||||
|
||||
// The file exists, read it and parse it.
|
||||
if (window.electron.exists(settingsPath)) {
|
||||
const configToml = await window.electron.readFile(settingsPath)
|
||||
const configToml = await window.electron.readFile(settingsPath, {
|
||||
encoding: 'utf-8',
|
||||
})
|
||||
const parsedAppConfig = parseAppSettings(configToml)
|
||||
if (err(parsedAppConfig)) {
|
||||
return Promise.reject(parsedAppConfig)
|
||||
@ -527,7 +531,9 @@ export const readTokenFile = async () => {
|
||||
let settingsPath = await getTokenFilePath()
|
||||
|
||||
if (window.electron.exists(settingsPath)) {
|
||||
const token: string = await window.electron.readFile(settingsPath)
|
||||
const token: string = await window.electron.readFile(settingsPath, {
|
||||
encoding: 'utf-8',
|
||||
})
|
||||
if (!token) return ''
|
||||
|
||||
return token
|
||||
|
@ -109,7 +109,9 @@ export const fileLoader: LoaderFunction = async (
|
||||
)
|
||||
}
|
||||
|
||||
code = await window.electron.readFile(currentFilePath)
|
||||
code = await window.electron.readFile(currentFilePath, {
|
||||
encoding: 'utf-8',
|
||||
})
|
||||
code = normalizeLineEndings(code)
|
||||
|
||||
// Update both the state and the editor's code.
|
||||
|
@ -74,7 +74,7 @@ const watchFileOff = (path: string, key: string) => {
|
||||
fsWatchListeners.set(path, watchers)
|
||||
}
|
||||
}
|
||||
const readFile = (path: string) => fs.readFile(path, 'utf-8')
|
||||
const readFile = fs.readFile
|
||||
// It seems like from the node source code this does not actually block but also
|
||||
// don't trust me on that (jess).
|
||||
const exists = (path: string) => fsSync.existsSync(path)
|
||||
|
Reference in New Issue
Block a user