{"record":{"id":"df62213a1a30480b","repo":"angular/components","slug":"player-not-initialized-before-name-called","errorCode":null,"errorMessage":"Player not initialized before ${name} called","messagePattern":"Player not initialized before (.+?) called","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/youtube-player/fake-youtube-player.ts","lineNumber":95,"sourceCode":"    return playerSpy;\n  });\n\n  playerSpy.addEventListener.and.callFake((name, listener) => {\n    const store: ListenersStore<typeof name> = boundListeners;\n    if (!store[name]) {\n      store[name] = new Set();\n    }\n    store[name].add(listener);\n  });\n\n  playerSpy.removeEventListener.and.callFake((name, listener) => {\n    boundListeners[name]?.delete(listener);\n  });\n\n  function eventHandlerFactory<EventName extends keyof YT.Events>(name: EventName) {\n    return (arg = {} as ListenerArg<EventName>) => {\n      if (!playerConfig) {\n        throw new Error(`Player not initialized before ${name} called`);\n      }\n\n      boundListeners[name]?.forEach(callback =>\n        (callback as (arg: ListenerArg<EventName>) => void)(arg),\n      );\n    };\n  }\n\n  const events: Required<YT.Events> = {\n    onReady: eventHandlerFactory('onReady'),\n    onStateChange: eventHandlerFactory('onStateChange'),\n    onPlaybackQualityChange: eventHandlerFactory('onPlaybackQualityChange'),\n    onPlaybackRateChange: eventHandlerFactory('onPlaybackRateChange'),\n    onError: eventHandlerFactory('onError'),\n    onApiChange: eventHandlerFactory('onApiChange'),\n    onAutoplayBlocked: eventHandlerFactory('onAutoplayBlocked'),\n  };\n","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/angular/components/blob/0411926e7d8ae06b32236ec1048a888cfad5abf2/src/youtube-player/fake-youtube-player.ts#L77-L113","documentation":"The fake YouTube player (used for testing/offline rendering) stores event handlers that dispatch to registered listeners. Its eventHandlerFactory checks that playerConfig has been set; invoking any event (e.g. onStateChange, onReady) before the player was initialized throws `Player not initialized before ${name} called`.","triggerScenarios":"Emitting a fake player event before createPlayer()/initialization populated playerConfig — e.g. tests firing events, or addEventListener callbacks invoked during setup before init completes.","commonSituations":"Unit tests that trigger events synchronously before awaiting player creation; mocking the YT iframe API where load completes after listeners already fired; fake player reused across tests with stale state.","solutions":["Await player initialization (the promise from the player factory / onReady) before firing or relying on events","In tests, ensure setup triggers init before dispatching events (e.g. flush microtasks / await fixture.whenStable)","Recreate the fake player if a previous init failed and left playerConfig unset"],"exampleFix":"// before\nplayer.addEventListener('onStateChange', handler);\nfireEvent('onStateChange'); // throws: playerConfig undefined\n\n// after\nawait player.init(); // ensures playerConfig is set\nplayer.addEventListener('onStateChange', handler);\nfireEvent('onStateChange');","handlingStrategy":"validation","validationCode":"// Ensure init before firing events in tests\nfunction assertInitialized(p: {playerConfig?: unknown}): void {\n  if (!p.playerConfig) throw new Error('Init fake player before dispatching events');\n}\n// usage\nawait fakePlayer.init();\nassertInitialized(fakePlayer);\nfireEvent('onStateChange');","typeGuard":"function isInitialized(p: {playerConfig?: unknown}): p is {playerConfig: object} {\n  return p.playerConfig != null;\n}","tryCatchPattern":"try {\n  fakePlayer.fireEvent('onStateChange');\n} catch (e) {\n  if (String(e?.message).startsWith('Player not initialized')) {\n    await fakePlayer.init();\n    fakePlayer.fireEvent('onStateChange');\n  }\n}","preventionTips":["Await fake player init/creation before triggering events","Register event listeners only after onReady","In tests, flush microtasks/timers so init completes before event dispatch","Recreate the fake player between tests to reset playerConfig"],"tags":["youtube-player","testing","initialization-order","mock"],"backgroundTag":"player-not-initialized","analyzedSha":"0411926e7d8ae06b32236ec1048a888cfad5abf2","analyzedAt":"2026-08-31T11:58:23.400Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}