Skip to content

Commit

Permalink
Merge branch 'develop' into bugfix-er/make-experiment-slug-unique
Browse files Browse the repository at this point in the history
  • Loading branch information
Evert-R committed Nov 21, 2024
2 parents 670cf79 + 2c9bc6e commit 586a953
Show file tree
Hide file tree
Showing 17 changed files with 611 additions and 138 deletions.
8 changes: 5 additions & 3 deletions backend/experiment/static/experiment_form.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ function initCollapsibleInlineForms() {
// create text element in button to show that the form is collapsed
collapsedInfo = document.createElement('small');
collapsedInfo.id = 'collapsed-info';
collapsedInfo.innerText = ' (-)';

collapsedInfo.innerText = ' \u25b2';
collapsedInfo.style.color = '#fff';
collapsedInfo.style.fontSize = '.75rem';
toggleButton.appendChild(collapsedInfo);
}

Expand All @@ -31,10 +33,10 @@ function initCollapsibleInlineForms() {

if (currentlyHidden) {
// create text element in button to show that the form is collapsed
collapsedInfo.innerText = ' (+)';
collapsedInfo.innerText = ' \u25bc';
} else {
// remove the text element in button to show that the form is expanded
collapsedInfo.innerText = ' (-)';
collapsedInfo.innerText = ' \u25b2';
}
});
});
Expand Down
4 changes: 2 additions & 2 deletions backend/experiment/templates/edit-sections.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ <h1>Edit sections for playlist: {{playlist.name}}</h1>
</td>
<td>
<input type="text" name="{{section.id}}_artist" maxlength="128" id="{{section.id}}_artist"
value="{{ section.artist_name('*')}}" >
value="{{ section.artist_name}}" placeholder="*">
</td>
<td>
<input type="text" name="{{section.id}}_name" maxlength="128" id="{{section.id}}_name"
value="{{ section.song_name('*')}}" >
value="{{ section.song_name}}" placeholder="*">
</td>
<td>
<input type="number" name="{{section.id}}_start_time" maxlength="128" required=""
Expand Down
68 changes: 38 additions & 30 deletions frontend/.pnp.cjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"classnames": "^2.2.6",
"email-validator": "^2.0.4",
"file-saver": "^2.0.5",
"next-share": "^0.27.0",
"qs": "^6.10.3",
"react": "18.3.1",
"react-dom": "18.3.1",
Expand All @@ -19,6 +18,7 @@
"react-router": "^6.25.1",
"react-router-dom": "^6.25.1",
"react-select": "^5.4.0",
"react-share": "^5.1.1",
"react-transition-group": "^4.4.5",
"sass": "^1.69.5",
"typescript": "^5.3.3",
Expand Down
144 changes: 120 additions & 24 deletions frontend/src/components/Histogram/Histogram.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,23 @@ import { render, act, waitFor } from '@testing-library/react';
import Histogram from './Histogram';

// Mock requestAnimationFrame and cancelAnimationFrame
vi.mock('global', () => ({
requestAnimationFrame: (callback: FrameRequestCallback): number => {
return setTimeout(callback, 0);
},
cancelAnimationFrame: (handle: number): void => {
clearTimeout(handle);
}
}));
vi.stubGlobal('requestAnimationFrame', (callback: FrameRequestCallback): number => {
return setTimeout(callback, 16); // Approximate 60 FPS
});

describe('Histogram', () => {
vi.stubGlobal('cancelAnimationFrame', (handle: number): void => {
clearTimeout(handle);
});

// Mock setInterval and clearInterval
vi.useFakeTimers();

describe('Histogram', () => {
let mockAnalyser: {
getByteFrequencyData: vi.Mock;
};

beforeEach(() => {
vi.useFakeTimers({ toFake: ['requestAnimationFrame'] });

// Mock the Web Audio API
mockAnalyser = {
getByteFrequencyData: vi.fn(),
Expand All @@ -31,7 +30,7 @@ describe('Histogram', () => {
});

afterEach(() => {
vi.useRealTimers();
vi.clearAllTimers();
vi.restoreAllMocks();
});

Expand Down Expand Up @@ -126,32 +125,129 @@ describe('Histogram', () => {
expect(mockAnalyser.getByteFrequencyData).toHaveBeenCalled();
});

it('does not update bar heights when not running', async () => {
it('does not update bar heights when not running', () => {
const bars = 5;
mockAnalyser.getByteFrequencyData.mockImplementation((array) => {
for (let i = 0; i < array.length; i++) {
array[i] = Math.floor(Math.random() * 256);
}
mockAnalyser.getByteFrequencyData.mockImplementation(() => {
// This should not be called when running is false
});

const { container, rerender } = render(<Histogram running={false} bars={bars} />);
const { container } = render(<Histogram running={false} bars={bars} />);

const getHeights = () => Array.from(container.querySelectorAll('.aha__histogram > div')).map(
(bar) => bar.style.height
const getHeights = () =>
Array.from(container.querySelectorAll('.aha__histogram > div')).map(
(bar) => bar.style.height
);

const initialHeights = getHeights();

// Advance timers to simulate time passing
act(() => {
vi.advanceTimersByTime(1000); // Advance time by 1 second
});

const updatedHeights = getHeights();

expect(initialHeights).to.deep.equal(updatedHeights);
expect(mockAnalyser.getByteFrequencyData).not.toHaveBeenCalled();
});

it('updates bar heights based on random data when random is true and running is true', async () => {
const bars = 5;

// Ensure the analyser does not provide data
mockAnalyser.getByteFrequencyData.mockImplementation(() => { });

const { container, rerender } = render(
<Histogram running={true} bars={bars} random={true} />
);

const getHeights = () =>
Array.from(container.querySelectorAll('.aha__histogram > div')).map(
(bar) => bar.style.height
);

const initialHeights = getHeights();

// Advance timers and trigger animation frame
await waitFor(async () => {
vi.advanceTimersToNextFrame();
await act(async () => {
vi.advanceTimersByTime(100);
});

rerender(<Histogram running={false} bars={bars} />);
rerender(<Histogram running={true} bars={bars} random={true} />);

const updatedHeights = getHeights();

expect(initialHeights).to.deep.equal(updatedHeights);
expect(initialHeights).not.to.deep.equal(updatedHeights);
expect(mockAnalyser.getByteFrequencyData).not.toHaveBeenCalled();
});

it('does not call getByteFrequencyData when random is true', async () => {
const bars = 5;

const { rerender } = render(
<Histogram running={true} bars={bars} random={true} />
);

// Advance timers and trigger animation frame
await act(async () => {
vi.advanceTimersByTime(100);
});

rerender(<Histogram running={true} bars={bars} random={true} />);

expect(mockAnalyser.getByteFrequencyData).not.toHaveBeenCalled();
});

it('updates bar heights based on random data at the specified interval', async () => {
const bars = 5;
const interval = 200;

const { container } = render(
<Histogram running={true} bars={bars} random={true} interval={interval} />
);

const getHeights = () =>
Array.from(container.querySelectorAll('.aha__histogram > div')).map(
(bar) => bar.style.height
);

const initialHeights = getHeights();

// Advance timers by the interval to trigger the update
await act(async () => {
vi.advanceTimersByTime(interval);
});

const updatedHeights = getHeights();

expect(initialHeights).not.to.deep.equal(updatedHeights);
});

it('updates bar heights based on frequency data using requestAnimationFrame', async () => {
const bars = 5;
mockAnalyser.getByteFrequencyData.mockImplementation((array) => {
for (let i = 0; i < array.length; i++) {
array[i] = Math.floor(Math.random() * 256);
}
});

const { container } = render(<Histogram running={true} bars={bars} />);

const getHeights = () =>
Array.from(container.querySelectorAll('.aha__histogram > div')).map(
(bar) => bar.style.height
);

const initialHeights = getHeights();

// Advance timers to simulate requestAnimationFrame calls
await act(async () => {
vi.advanceTimersByTime(16); // Approximate time for one frame at 60 FPS
});

const updatedHeights = getHeights();

expect(initialHeights).not.to.deep.equal(updatedHeights);
expect(mockAnalyser.getByteFrequencyData).toHaveBeenCalled();
});
});
Loading

0 comments on commit 586a953

Please sign in to comment.