wavesurfer.js icon indicating copy to clipboard operation
wavesurfer.js copied to clipboard

Jest error: ReferenceError: self is not defined

Open geraintwhite opened this issue 4 years ago • 13 comments

In the latest version of the library, we get the following error when using jest:

    ReferenceError: self is not defined

      4 | import { findWithType } from 'react-shallow-testutils';
      5 | import ShallowRenderer from 'react-test-renderer/shallow';
    > 6 | import WaveSurfer from 'wavesurfer.js';
        | ^

This was caused by a change removing globalObject: 'this' from the build config in https://github.com/katspaugh/wavesurfer.js/commit/d27b75e29b16e1b0d425eefa83bd0b0e1891f067.

There is a workaround by setting testEnvironment: 'jsdom' in the jest config, but this causes issues for things in the node environment.

geraintwhite avatar Aug 31 '21 10:08 geraintwhite

thanks for the report. If you can figure out what changed (in probably webpack), please open a pull request.

thijstriemstra avatar Aug 31 '21 22:08 thijstriemstra

because adding globalObject: 'this' causes npm run test to fail.

thijstriemstra avatar Aug 31 '21 22:08 thijstriemstra

FWIW if you're just looking to import wavesurfer in a node context (but not run it), you can just shim window and self:

global.self = global;
global.window = {};

This is useful for SSR react components that execute WaveSurfer.create in a useEffect hook.

noslouch avatar Sep 29 '21 15:09 noslouch

What is the solution here?

I'm unable to use the library in a Next.js environment.

Server Error
ReferenceError: self is not defined

Object.<anonymous>
file:///node_modules/wavesurfer.js/dist/wavesurfer.js (15:4)

@noslouch I don't understand your solution. How do I replicate this "shim" in a component? What is that global variable?

bencehusi avatar Jan 05 '22 13:01 bencehusi

@bencehusi global is a node global. What happens if you add that code to your _app.js file?

noslouch avatar Jan 05 '22 14:01 noslouch

Did not really work.

Anyone who is looking for a Next.js solution, use the dynamic loader to load your component that contains the wavesurfer import:

import dynamic from 'next/dynamic'

const PodcastPlayer = dynamic(
    () => import('@/components/atoms/PodcastPlayer'),
    { ssr: false }
)

bencehusi avatar Jan 05 '22 14:01 bencehusi

Did not really work.

Anyone who is looking for a Next.js solution, use the dynamic loader to load your component that contains the wavesurfer import:

import dynamic from 'next/dynamic'

const PodcastPlayer = dynamic(
    () => import('@/components/atoms/PodcastPlayer'),
    { ssr: false }
)

Does this work with dynamic routing?

vinikatyal avatar Feb 20 '22 14:02 vinikatyal

I'm having this issue in Sveltekit. I tried shimming global, but it doesn't seem to work. Has anyone found a solution?

Edit: For more clarification, it happens about every other reload in dev, and the production build fails completely. Not sure if that helps.

iandoesallthethings avatar Feb 23 '22 02:02 iandoesallthethings

Same here with Vue/Nuxt

command-tab avatar Feb 23 '22 02:02 command-tab

@iandoesallthethings I made it work in Sveltekit by dynamically importing the package in onMount:

	const initProgress = async () => {
		try {
			const waveSurfer = (await import('wavesurfer.js')).default;
			const audio = waveSurfer.create({
				container: `#my-id`,
				waveColor: '#000000',
				progressColor: '#ffffff'
			});
			audio.load(url);
		} catch (error) {
			console.error(error);
		}
	};

	onMount(() => {
		initProgress();
	});

f-elix avatar Mar 15 '22 21:03 f-elix

@iandoesallthethings I made it work in Sveltekit by dynamically importing the package in onMount:

	const initProgress = async () => {
		try {
			const waveSurfer = (await import('wavesurfer.js')).default;
			const audio = waveSurfer.create({
				container: `#my-id`,
				waveColor: '#000000',
				progressColor: '#ffffff'
			});
			audio.load(url);
		} catch (error) {
			console.error(error);
		}
	};

	onMount(() => {
		initProgress();
	});

Thanks f-elix for this great tip. Your example works for the basic player but when I tried addding wavesurfer plugins, it doesn't work. Have you got plugins working? Cheers.

const initProgress = async () => {
	try {
		let WaveSurfer = (await import('wavesurfer.js')).default;
		let audio = WaveSurfer.create({
			container: '#waveform',
    plugins: [
        WaveSurfer.markers.create({
            markers: [
                {
                    time: 5.5,
                    label: "V1",
                    color: '#ff990a'
                },
                {
                    time: 10,
                    label: "V2",
                    color: '#00ffcc',
                    position: 'top'
                }
            ]
        })
  ]
		});
		audio.load('./static/strings.wav');

            audio.on('ready', function () {
              audio.play();
           });
	} catch (error) {
		console.error(error);
	}
};

onMount(() => {
	initProgress();

});

99bits avatar Mar 16 '22 19:03 99bits

@99bits No I haven't used plugins, so can't really help you there unfortunately.

f-elix avatar Mar 16 '22 19:03 f-elix

并没有真正起作用。

任何正在寻找 Next.js 解决方案的人,使用动态加载器来加载包含 wavesurfer 导入的组件:

import dynamic from 'next/dynamic'

const PodcastPlayer = dynamic(
    () => import('@/components/atoms/PodcastPlayer'),
    { ssr: false }
)

I found the mistake error

    main › ReferenceError: window is not defined
    at /Users/xxx/renderer/.next/server/pages/home.js:197:28
    at Object.<anonymous> (/Users/xxx/renderer/.next/server/pages/home.js:209:10)
    at Module._compile (internal/modules/cjs/loader.js:1078:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1108:10)
    at Module.load (internal/modules/cjs/loader.js:935:32)
    at Module._load (internal/modules/cjs/loader.js:776:14)
    at Function.f._load (electron/js2c/asar_bundle.js:5:12913)
    at Module.require (internal/modules/cjs/loader.js:959:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at requirePage (/Users/xxx/node_modules/next/dist/next-server/server/require.js:1:1519)
    at loadComponents (/Users/xxx/node_modules/next/dist/next-server/server/load-components.js:1:1442)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at async DevServer.findPageComponents (/Users/xxx/node_modules/next/dist/next-server/server/next-server.js:77:257)
    at async DevServer.renderToHTML (/Users/xxx/node_modules/next/dist/next-server/server/next-server.js:138:542)
    at async DevServer.renderToHTML (/Users/xxx/node_modules/next/dist/server/next-dev-server.js:36:578)
    at async DevServer.render (/Users/xxx/node_modules/next/dist/next-server/server/next-server.js:75:160)

luokunman avatar Aug 24 '22 06:08 luokunman

This is brilliant, thank you so much! Worked for me in Next.js

frg100 avatar Nov 01 '22 03:11 frg100

A similar issue has come up before (#751). I'm hoping this time someone might add a couple of guard statements so wavesurfer doesn't assume window exists.

cco3 avatar Nov 01 '22 15:11 cco3

Thanks! it works for me

ShadowMaking avatar Apr 21 '23 10:04 ShadowMaking