Skip to content

Commit

Permalink
refactor: Convert Consent component to TS and slightly update types
Browse files Browse the repository at this point in the history
  • Loading branch information
drikusroor committed Jul 4, 2024
1 parent 865dd72 commit bcbb665
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 25 deletions.
6 changes: 4 additions & 2 deletions frontend/src/API.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,14 @@ export const useParticipantScores = () =>
export const useParticipantLink = () =>
useGet(API_BASE_URL + URLS.participant.link);

type ConsentResponse = boolean | null;

export const useConsent = (slug: string) =>
useGet(API_BASE_URL + URLS.result.get('consent_' + slug));
useGet<ConsentResponse>(API_BASE_URL + URLS.result.get('consent_' + slug));

interface CreateConsentParams {
block: Block;
participant: Participant;
participant: Pick<Participant, 'csrf_token'>;
}

/** Create consent for given experiment */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React from 'react';
import { fireEvent, render, waitFor } from '@testing-library/react';
import Consent from './Consent';
import Consent, { ConsentProps } from './Consent';
import { useConsent } from '../../API'
import { saveAs } from 'file-saver';
import { vi } from 'vitest';
import { vi, Mock, expect, it, describe, } from 'vitest';

global.Blob = vi.fn().mockImplementation((content, options) => ({
content,
Expand All @@ -26,51 +25,60 @@ const mockBlock = {
loading_text: 'Loading...',
};

const getConsentProps: (overrides?: Partial<ConsentProps>) => ConsentProps = (overrides) => ({
title: 'Consent',
text: '<p>Consent Text</p>',
block: mockBlock,
participant: { csrf_token: '42' },
onNext: vi.fn(),
confirm: 'Agree',
deny: 'Disagree',
...overrides,
});

describe('Consent', () => {
it('renders loading state correctly', () => {
useConsent.mockReturnValue([null, true]); // Mock loading state
const { getByText } = render(<Consent block={{ slug: 'test-experiment', loading_text: 'Loading...' }} />);
expect(document.body.contains(getByText('Loading...'))).to.be.true;
(useConsent as Mock).mockReturnValue([null, true]); // Mock loading state
const { getByText } = render(<Consent {...getConsentProps({ block: { slug: 'test-experiment', loading_text: 'Loading...' } })} />);
expect(document.body.contains(getByText('Loading...'))).toBe(true);
});

it('renders consent text when not loading', () => {
useConsent.mockReturnValue([null, false]);
const { getByText } = render(<Consent text="<p>Consent Text</p>" block={mockBlock} />);
expect(document.body.contains(getByText('Consent Text'))).to.be.true;
(useConsent as Mock).mockReturnValue([null, false]);
const { getByText } = render(<Consent {...getConsentProps({ text: '<p>Consent Text</p>', block: { slug: 'test-experiment', loading_text: 'Loading...' } })} />);

expect(document.body.contains(getByText('Consent Text'))).toBe(true);
});

it('calls onNext when Agree button is clicked', async () => {
useConsent.mockReturnValue([null, false]);
(useConsent as Mock).mockReturnValue([null, false]);
const onNext = vi.fn();
const { getByText } = render(<Consent onNext={onNext} confirm="Agree" block={mockBlock} />);
const { getByText } = render(<Consent {...getConsentProps({ confirm: 'Agree', block: mockBlock, onNext })} />);
fireEvent.click(getByText('Agree'));

await waitFor(() => expect(onNext).toHaveBeenCalled());
});

it('triggers download when Download button is clicked', async () => {
useConsent.mockReturnValue([null, false]);
const { getByTestId } = render(<Consent text="<p>Consent Text</p>" block={mockBlock} />);
(useConsent as Mock).mockReturnValue([null, false]);
const { getByTestId } = render(<Consent {...getConsentProps()} />);
fireEvent.click(getByTestId('download-button'));

await waitFor(() => expect(saveAs).toHaveBeenCalled());
});

it('auto advances if consent is already given', () => {
useConsent.mockReturnValue([true, false]);
(useConsent as Mock).mockReturnValue([true, false]);
const onNext = vi.fn();
render(<Consent onNext={onNext} block={mockBlock} />);
render(<Consent {...getConsentProps({ block: mockBlock, onNext })} />);
expect(onNext).toHaveBeenCalled();
});

it('calculates style for consent text correctly', () => {
useConsent.mockReturnValue([null, false]);
(useConsent as Mock).mockReturnValue([null, false]);
Object.defineProperty(window, 'innerHeight', { writable: true, configurable: true, value: 800 });
const { getByTestId } = render(<Consent text="<p>Consent Text</p>" block={mockBlock} />);
const { getByTestId } = render(<Consent {...getConsentProps()} />);
const consentText = getByTestId('consent-text');
expect(consentText.style.height).toBe('500px');
});



});
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
import React, { useEffect } from "react";
import { useEffect } from "react";
import { saveAs } from 'file-saver';

import { URLS } from "@/config";
import Button from "../Button/Button";
import Loading from "../Loading/Loading";
import { createConsent, useConsent } from "../../API";
import classNames from "classnames";
import Participant from "@/types/Participant";

export interface ConsentProps {
title: string;
text: string;
block: any;
participant: Pick<Participant, 'csrf_token'>;
onNext: () => void;
confirm: string;
deny: string;
}

/** Consent is an block view that shows the consent text, and handles agreement/stop actions */
const Consent = ({ title, text, block, participant, onNext, confirm, deny }) => {
const Consent = ({ title, text, block, participant, onNext, confirm, deny }: ConsentProps) => {
const [consent, loadingConsent] = useConsent(block.slug);
const urlQueryString = window.location.search;

Expand All @@ -30,7 +41,7 @@ const Consent = ({ title, text, block, participant, onNext, confirm, deny }) =>

const onDownload = async () => {
const doc = new DOMParser().parseFromString(text, 'text/html');
const txt = doc.body.textContent.split(' ').join('');
const txt = doc.body.textContent ? doc.body.textContent.split(' ').join('') : '';
const blob = new Blob([txt], { type: "text/plain;charset=utf-8" });
saveAs(blob, 'consent.txt');
}
Expand Down

0 comments on commit bcbb665

Please sign in to comment.