Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.1.2 Causes "Expression expected" errors #4872

Closed
6 tasks done
EvHaus opened this issue Jan 4, 2024 · 15 comments · Fixed by #4873
Closed
6 tasks done

v1.1.2 Causes "Expression expected" errors #4872

EvHaus opened this issue Jan 4, 2024 · 15 comments · Fixed by #4873
Assignees
Labels
p4-important Violate documented behavior or significantly improves performance (priority)

Comments

@EvHaus
Copy link
Contributor

EvHaus commented Jan 4, 2024

Describe the bug

After upgrading from v1.1.1 to v1.1.2 all my tests are failing with:

Error: Expression expected
 ❯ error node_modules/.pnpm/rollup@4.9.2/node_modules/rollup/dist/es/shared/parseAst.js:337:30
 ❯ nodeConverters node_modules/.pnpm/rollup@4.9.2/node_modules/rollup/dist/es/shared/parseAst.js:2084:9
 ❯ convertNode node_modules/.pnpm/rollup@4.9.2/node_modules/rollup/dist/es/shared/parseAst.js:969:12
 ❯ convertProgram node_modules/.pnpm/rollup@4.9.2/node_modules/rollup/dist/es/shared/parseAst.js:960:48
 ❯ parseAstAsync node_modules/.pnpm/rollup@4.9.2/node_modules/rollup/dist/es/shared/parseAst.js:2150:20
 ❯ ssrTransformScript node_modules/.pnpm/vite@5.0.10_@types+node@20.10.6/node_modules/vite/dist/node/chunks/dep-R0I0XnyH.js:49846:15
 ❯ loadAndTransform node_modules/.pnpm/vite@5.0.10_@types+node@20.10.6/node_modules/vite/dist/node/chunks/dep-R0I0XnyH.js:49434:11

It seems to happen if you have:

  • A setup file
  • That setup file imports something from another file
  • You pass that imported data to a mockImplementation method

Really weird...

Reproduction

Was pretty easy to create a repro:

https://stackblitz.com/edit/vitest-dev-vitest-3w2rlj?file=setupFile.ts

System Info

System:
    OS: macOS 14.1.2
    CPU: (8) arm64 Apple M1 Pro
    Memory: 426.56 MB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.3.1 - ~/.nvm/versions/node/v20.3.1/bin/node
    Yarn: 1.22.19 - ~/.nvm/versions/node/v20.3.1/bin/yarn
    npm: 9.8.0 - ~/.nvm/versions/node/v20.3.1/bin/npm
    pnpm: 8.10.4 - ~/.nvm/versions/node/v20.3.1/bin/pnpm
    bun: 1.0.18 - ~/.bun/bin/bun
  Browsers:
    Chrome: 120.0.6099.129
    Chrome Canary: 122.0.6225.0
    Edge: 120.0.2210.91
    Safari: 17.1.2
  npmPackages:
    @vitejs/plugin-react: 4.2.1 => 4.2.1
    @vitest/coverage-v8: 1.1.2 => 1.1.2
    vite: 5.0.10 => 5.0.10
    vitest: 1.1.2 => 1.1.2

Used Package Manager

pnpm

Validations

@sheremet-va
Copy link
Member

sheremet-va commented Jan 4, 2024

Looks like this is a regression from #4664. The code that mocker produces is invalid (mock factory is moved too soon?):

const { vi } = await import('vitest')
vi.mock("somemodule", async () => {
  return {
    getServerSession: vi.fn().mockImplementation(() => ({
      user
    }))
  };
});
const __vi_import_0__ = await import('./user')


: __vi_import_0__.default

cc @Dunqing

@sheremet-va sheremet-va added bug p4-important Violate documented behavior or significantly improves performance (priority) and removed pending triage labels Jan 4, 2024
@ghiscoding
Copy link
Contributor

ghiscoding commented Jan 4, 2024

I also have similar problems in Lerna-Lite but with different output, it was working fine with v1.1.1

FAIL  packages/filter-packages/src/__tests__/get-filtered-packages.spec.ts [ packages/filter-packages/src/__tests__/get-filtered-packages.spec.ts ]
Error: [vitest] Cannot mock "npmlog" because it is already loaded. Did you import it in a setup file?

Please, remove the import if you want static imports to be mocked, or clear module cache by calling "vi.resetModules()" before mocking if you are going to import the file again. See: https://vitest.dev/guide/common-errors.html#cannot-mock-mocked-file.js-because-it-is-already-loaded
 ❯ packages/filter-packages/src/__tests__/get-filtered-packages.spec.ts:21:25

and I have this mock on top of my test (see real test here)

import { beforeAll, expect, test, vi } from 'vitest';

const { mockNotice } = vi.hoisted(() => ({ mockNotice: vi.fn() }));
vi.mock('npmlog', async () => ({
  ...(await vi.importActual<any>('npmlog')),
  notice: mockNotice,
}));

For reference, the failing GitHub Action job and the unit test

@sheremet-va
Copy link
Member

sheremet-va commented Jan 4, 2024

I have this mock on top of my test (see real test here)

It doesn't matter where you put it, it is always hoisted.

This is not a bug, you import npmlog inside silence-logging.ts which is imported as a setup file before the test starts running, so it might not have an effect if it was imported inside another file that is not mocked. You need to follow the instructions in the error message.

@diegohaz
Copy link

diegohaz commented Jan 4, 2024

I'm not sure if it's the same issue, but I'm also seeing errors related to mocking. I use this snippet to mock React 18 features when using React 17. But apparently, this useMemo call is not working with 1.1.2 anymore:

import { useMemo, version } from "react";

if (version.startsWith("17")) {
  vi.mock("react", async () => {
    const actual = await vi.importActual<typeof import("react")>("react");
    let id = 0;
    const mocks = {
      startTransition: (v: () => any) => v(),
      useDeferredValue: <T>(v: T) => v,
      useTransition: () => [false, (v: () => any) => v()],
      useId: () => useMemo(() => `id-${id++}`, []),
    };
    return { ...mocks, ...actual };
  });
}
ReferenceError: useMemo is not defined

Edit: Changing it to actual.useMemo seems to resolve the problem.

@Dunqing
Copy link
Member

Dunqing commented Jan 5, 2024

Looks like this is a regression from #4664. The code that mocker produces is invalid (mock factory is moved too soon?):

const { vi } = await import('vitest')
vi.mock("somemodule", async () => {
  return {
    getServerSession: vi.fn().mockImplementation(() => ({
      user
    }))
  };
});
const __vi_import_0__ = await import('./user')


: __vi_import_0__.default

cc @Dunqing

Yes, sorry about that. The import was modified before we moved the mocks, so the code has changed. We need to move the latest code

@sheremet-va
Copy link
Member

This is not a bug, you import npmlog inside silence-logging.ts which is imported as a setup file before the test starts running, so it might not have an effect if it was imported inside another file that is not mocked. You need to follow the instructions in the error message.

We might need to improve the check to target this only for cases when this would fail but it's a bit expensive to do for each import.

@bakku
Copy link

bakku commented Jan 15, 2024

Should it be fixed in v1.2.0? Because we are still getting this issue with v1.2.0:

// <project-root>/vitest.setup.ts
import { mocks } from './src/testing';
console.log(mocks.someMock);

// <project-root>/src/testing.ts
import { vi } from 'vitest';

export const mocks = vi.hoisted(() => ({
  someMock: vi.fn(),
}));

When running the tests:

Error: Unexpected eof
 ❯ error node_modules/rollup/dist/es/shared/parseAst.js:337:30
 ❯ nodeConverters node_modules/rollup/dist/es/shared/parseAst.js:2084:9
 ❯ convertNode node_modules/rollup/dist/es/shared/parseAst.js:969:12
 ❯ convertProgram node_modules/rollup/dist/es/shared/parseAst.js:960:48
 ❯ parseAstAsync node_modules/rollup/dist/es/shared/parseAst.js:2150:20
 ❯ ssrTransformScript node_modules/vite/dist/node/chunks/dep-V3BH7oO1.js:50201:15
 ❯ loadAndTransform node_modules/vite/dist/node/chunks/dep-V3BH7oO1.js:49789:11

@sheremet-va
Copy link
Member

Should it be fixed in v1.2.0? Because we are still getting this issue with v1.2.0:

Why do you use vi.hoisted if your code is located in another file? (i.e. it's exported)

@bakku
Copy link

bakku commented Jan 15, 2024

We have a set of mocks in a separate file (in my example the src/testing.ts file) which are exported there and are then imported and used in different tests and also imported in our setup file.

We wanted to migrate from vitest 0.34 where this structure worked to v1.2.0 but we are getting this error now.

@sheremet-va
Copy link
Member

We have a set of mocks in a separate file (in my example the src/testing.ts file) which are exported there and are then imported and used in different tests and also imported in our setup file.

Yes, but why are they wrapped in vi.hoisted? It doesn't make sense to call it for a variable that you don't use in the same file. That's the whole reason it exists. If you import it in another file, you control the hoisting by placing the import first.

@bakku
Copy link

bakku commented Jan 15, 2024

We are also using it in the file itself. I'll expand the example a bit to show how we have it structured:

In the setup file we are setting the mocks:

// <project-root>/vitest.setup.ts
import { vi } from 'vitest';
import { mocks } from './src/testing';

vi.mock('@/someLib', () => ({
  someFunc: mocks.someFunc,
}));

In the separate file we define the mocks and also have some helper functions for our tests in which we also use the mocks:

// <project-root>/src/testing.ts
import { vi } from 'vitest';

export const mocks = vi.hoisted(() => ({
  someFunc: vi.fn(),
}));

export const setSomeFuncReturnValue = (a: string) => {
  mocks.someFunc.mockReturnValue({
    a,
    b: 'Some Default Value',
  });
};

Here is how a test looks like:

// example test
describe('some test', () => {
  it('tests', () => {
    setSomeFuncReturnValue('Some other Value');

    // expectations...
  })
})

@sheremet-va
Copy link
Member

You are just showing how you use it. I am asking why you are using vi.hoisted here. It doesn't do anything in your examples. Hosted doesn't affect how variables are hoisted outside of that file.

In the first example you should even get a syntax error because vi.mock is executed before the import - it doesn't have access to mocks.

@bakku
Copy link

bakku commented Jan 15, 2024

We are not really using it due to any specific reason, other than finding code examples in the documentation and using them, I think..

In vitest 0.34 this worked in general, no syntax error too.

But what I understand from you is that this is not expected to work anyway and we should restructure our approach and not use vi.hoisted there.. I see.

@sheremet-va
Copy link
Member

Yes, you can just remove vi.hoisted wrapper there. I am preparing a PR to throw a syntax error with a more clear error message in this case.

@mabecth
Copy link

mabecth commented Jan 22, 2024

Getting the same error for v1.2.1:

Error: Expression expected ❯ error node_modules/rollup/dist/es/shared/parseAst.js:337:30 ❯ nodeConverters node_modules/rollup/dist/es/shared/parseAst.js:2084:9 ❯ convertNode node_modules/rollup/dist/es/shared/parseAst.js:969:12 ❯ convertProgram node_modules/rollup/dist/es/shared/parseAst.js:960:48 ❯ parseAstAsync node_modules/rollup/dist/es/shared/parseAst.js:2150:20 ❯ ssrTransformScript node_modules/vite/dist/node/chunks/dep-V3BH7oO1.js:50201:15

@github-actions github-actions bot locked and limited conversation to collaborators Feb 6, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
p4-important Violate documented behavior or significantly improves performance (priority)
Projects
None yet
7 participants