Greetings! I am building Drum Machine in React.js, and got everything working, and all tests except 6 fail. Problem is, I do have keydown handler for it. I tried different approaches but they all fail tests with this error:
- When I press the trigger key associated with each .drum-pad, the audio clip contained in its child element should be triggered (e.g. pressing the Q key should trigger the drum pad which contains the string “Q”, pressing the W key should trigger the drum pad which contains the string “W”, etc.).
No audio plays when the Q key is pressed : expected true to be false
AssertionError: No audio plays when the Q key is pressed : expected true to be false
Which is not true, because application works as intented and I can’t get past this test with different approaches.
My current setup:
class App extends Component {
[...]
playSoundFile = soundId => {
this.updateDisplay(soundId);
const sound = document.getElementById(soundId);
sound.currentTime = 0;
sound.play();
};
keyDownHandler = e => {
switch (e.key) {
case "q":
this.playSoundFile("Q");
break;
case "w":
this.playSoundFile("W");
break;
case "e":
this.playSoundFile("E");
break;
case "a":
this.playSoundFile("A");
break;
case "s":
this.playSoundFile("S");
break;
case "d":
this.playSoundFile("D");
break;
case "z":
this.playSoundFile("Z");
break;
case "x":
this.playSoundFile("X");
break;
case "c":
this.playSoundFile("C");
break;
}
};
[...]
componentDidMount() {
document.addEventListener("keydown", this.keyDownHandler);
}
componentWillUnmount() {
document.removeEventListener("keydown", this.keyDownHandler);
}
render() {
return (
<div tabIndex="0" className="App">
<DrumMachine
displayText={this.state.drumDisplayText}
playHandler={this.playSoundFile}
/>
<ControlPanel />
<Piano />
</div>
);
}
}
From user perspective it works just as technical requirement states and it plays correct sound files.
This is my #3 approach to keyhandler, because I already tried different cases and all previus versions failed that test as well, while technically working 100% as intended.
My first iteration looked like this:
render() {
return (
<div tabIndex="0" className="App" onKeyDown={this.keyDownHandler}>
<DrumMachine
displayText={this.state.drumDisplayText}
playHandler={this.playSoundFile}
/>
<ControlPanel />
<Piano />
</div>
);
}
I reiterated this approach because I had suspicion that it conflicts with way react components do “onKeyDown”, so I moved to case 2:
componentDidMount() {
this.appDiv.addEventListener("keydown", this.keyDownHandler);
this.appDiv.focus();
}
componentWillUnmount() {
this.appDiv.removeEventListener("keydown", this.keyDownHandler);
}
render() {
return (
<div tabIndex="0" className="App" ref={ref => (this.appDiv = ref)}>
<DrumMachine
displayText={this.state.drumDisplayText}
playHandler={this.playSoundFile}
/>
<ControlPanel />
<Piano />
</div>
);
}
But this did not pass test either. At this point I had suspicion that maybe it is because app container looses focus when test popup shows, so I just hijacked it on document as in start.
But that still did not pass it despite fact that all functionality works perfectly and when user presses key it actually works properly.
What am I doing wrong here? I don’t have production build yet, but I will try to post prototype demonstrating this later.