Skip to content

Conversation

kylewalke
Copy link
Contributor

What does this PR do?

Adding E2E tests with Playwright to the repo

What issues does this PR fix or reference?

@W-19444022@

@kylewalke kylewalke requested a review from a team as a code owner September 2, 2025 19:33
@kylewalke kylewalke changed the base branch from main to tdx26/main September 2, 2025 19:33
@kylewalke kylewalke requested a review from peternhale September 2, 2025 23:48
Copy link
Contributor

@mshanemc mshanemc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

meta: please run npx knip to cleanup unused exports. I don't see a lot of refactoring cleanups or "clean up things while doing another fix/feature", so if we let in a bunch of slop and dead code, it'll be there for a long time.


on:
push:
branches: [main, kyledev/e2eTesting]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you want to clean this up, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I need it to be there for the duration of the branches existence (this PR) but it would be removed after the fact since this branch will get deleted.

│ ├── outline-helpers.ts # Outline view specific helpers
│ └── global.ts # Global setup and teardown functions
├── test-server.js # VS Code Web test server
├── playwright.config.ts # Playwright configuration
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I need this AI slop. Maybe only point out the interesting/unexpected parts?

file/folder names should be doing most of the work.

And trying to maintain it for every file is gonna suck.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I can reduce it down to a more general overview and less nitty gritty that will change a lot over time. It's nice to see while working on it but I'm totally ok not immortalizing it.

return typeof globalThis !== 'undefined' &&
'indexedDB' in globalThis &&
(globalThis as any).indexedDB !== null;
return (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is that a real scenario (browser without indexDB?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Browser no but desktop wouldn't have it, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for context, these were all linting auto-fixes I noticed needed auto-fixing while workin on the e2e tests so no functional changes in the apex-ls package files.


if (isVisible) {
// Hover to show file selection in debug mode
if (process.env.DEBUG_MODE) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

meta: I don't love that there's all these different behaviors depending on the env. Have you found these to be really useful, vs. the tradeoffs of

  1. complexity + extra code
  2. works locally then fails in CI

Like, if we're concerned about parallelism and accuracy, I'd rather run 1-test-per-container in gha than I would run them all sequentially and have that be different from desktop.

Curious on your perspective.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

During dev I was having some issues running parallel local headless vs headed mode and with/without the playwright UI, so these env variables were to help nail down exactly what should happen when I run the different scripts. I haven't done as much extensive testing in the CI env to make sure that's all as robust as it probably needs to be (meaning even with what I have here the option2 is the result). I was thinking the tests should be run sequentially instead of parallel because I want to see in order that the tests pass for activating the extension first, then that the server was initialized, then that the file is opened, etc. Since to me, if something goes wrong in that sequential chain, I would then know where to look to fix things. Especially since most of the additional tests are dependent on each other to pass.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do want CI and desktop to run as similarly as possible though, headless or not, I think sequential execution should be the approach still.

// Hover to show file selection in debug mode
if (process.env.DEBUG_MODE) {
await clsFile.hover();
await page.waitForTimeout(500);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to avoid waitForTimeout. It's hard to keep Cursor from doing it, but the tests should be waiting for some screen element, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can abide by that. It's really easy/convenient but introduces inaccurate cues for when to move on to the next step of a test. I can remove them in place of more precise triggers.

}

// Create test workspace using fixtures
const workspacePath = path.resolve(__dirname, '../test-workspace');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are all the tests going to try to use the same workspace? would it make more sense to have a helper so that a test can set up its workspace (preferably in /tmp) with the files it needs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. The setup I have right now uses the same directory that is created as the test workspace in the e2e-tests directory so that it's also easy to find. Is there additional benefit to the test workspace and files living in tmp? I think for the base e2e's this is fine but I'd be okay expanding the setup to move the workspace later.


// Create test workspace using fixtures
const workspacePath = path.resolve(__dirname, '../test-workspace');
if (!fs.existsSync(workspacePath)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can just mkdir without checking for existence. That's one of the nice things about recursive

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not generally a fan of globalSetup stuff, hopefully it can be removed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know that about mkdir! nice, okay I can clean that up. Do you mean you don't like setup steps at all or just like the globalSetup naming scheme?

*
* @param _config - Playwright configuration
*/
export async function globalSetup(_config: FullConfig): Promise<void> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused? why have it?

Copy link
Contributor Author

@kylewalke kylewalke Sep 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good eye
image

/**
* Sample Apex class with basic methods for testing language features.
*/
export const HELLO_WORLD_CLASS: SampleFile = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably 1 file per sample class? other than apex-samples what else would there be in fixtures since this is an Apex LS?

And it's weird to have these separated from the outline-helpers stuff. Like, what if some of these had the EXPECTED_APEX_SYMBOLS so that anything using them could access both, and when you change something here you don't have to change the other file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Come to think of it, this is a good point. There's not gonna be much else we need to generate so I think this could get merged into the other helpers.

/**
* Sample Apex trigger for testing trigger-specific functionality.
*/
export const ACCOUNT_TRIGGER: SampleFile = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you actually using these for anything? I see helloWorld and complex used but not the soql/trigger.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking I might add some tests to make sure that the different file ending types worked. like .trigger, .cls, and .apex but I didn't flesh out those test cases. This is an artifact from that. I want to get one of those in eventually to make sure the outline and extension activation works for all 3 filetypes still but doesn't need to be part of this initial work.

- Fix Playwright webServer configuration to use correct working directory
- Add dynamic cwd detection to run npm scripts from root when executed from e2e-tests directory
- Update GitHub Actions workflow to properly handle directory context
- Ensure test:e2e:server script can be found and executed correctly

This resolves the remaining e2e test failures by ensuring the webServer
can properly locate and execute the test server startup script.
- Set headless: true in CI environments to avoid X11 display issues
- Add CI-specific Chrome launch arguments for better stability
- Keep headed mode for local development debugging
- Resolves browser launch failures in GitHub Actions runners

This fixes the 'Missing X server or $DISPLAY' error that was preventing
the test server from starting in CI environments.
@kylewalke kylewalke requested a review from mshanemc September 4, 2025 22:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants