Skip to content

Commit

Permalink
Merge pull request #118 from mitaai/blms/tests
Browse files Browse the repository at this point in the history
#17 tests
  • Loading branch information
blms authored Dec 29, 2020
2 parents cc8858f + 7c1af2e commit 0fe950e
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 29 deletions.
59 changes: 44 additions & 15 deletions src/components/HeatMap/HeatMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,54 @@ import $ from 'jquery';
import { DocumentFiltersContext, DocumentAnnotationsContext } from '../../contexts/DocumentContext';


function HeatMap({ pdf }) {
const HeatMap = ({ pdf }) => {
const lineHeight = 18;
const documentHeight = $('#document-container').height() || 0;
let scaleFactor = $('#document-container').get(0) === undefined ? 1 : $('#document-container').height() / $('#document-container').get(0).scrollHeight;
const scaleFactor = $('#document-container').get(0) === undefined
? 1
: $('#document-container').height() / $('#document-container').get(0).scrollHeight;
const minStrokeHeight = 1;
const offsetTop = $('#document-container').offset() === undefined ? 0 : $('#document-container').offset().top;
const grandularity = lineHeight * scaleFactor >= minStrokeHeight ? lineHeight : Math.ceil(minStrokeHeight / scaleFactor);
const offsetTop = $('#document-container').offset() === undefined
? 0
: $('#document-container').offset().top;
const grandularity = lineHeight * scaleFactor >= minStrokeHeight
? lineHeight
: Math.ceil(minStrokeHeight / scaleFactor);
const [channelAnnotations] = useContext(DocumentAnnotationsContext);
const [documentFilters] = useContext(DocumentFiltersContext);
const n = (Math.ceil($('#document-card-container').height() / grandularity));
const map = new Array(isNaN(n) ? 0 : n);
const map = new Array(Number.isNaN(n) ? 0 : n);

for (const side in channelAnnotations) {
if (channelAnnotations[side] !== null) {
for (const anno of channelAnnotations[side]) {
if (documentFilters.annotationIds[side] !== null && documentFilters.annotationIds[side].includes(anno._id)) {
if (documentFilters.annotationIds[side] !== null
&& documentFilters.annotationIds[side].includes(anno._id)) {
if (anno.position.height !== undefined) {
let h = anno.position.height;
// if for some reason the height of this annotation is a negative number we are going to recalculate the value in the loop
// if for some reason the height of this annotation is a negative number,
// recalculate the value in the loop
if (h < 0) {
const annotationBeginning = $(`#document-content-container span[annotation-id='${anno._id}'] .annotation-beginning-marker`);
const annotationEnding = $(`#document-content-container span[annotation-id='${anno._id}'] .annotation-ending-marker`);
if (annotationBeginning.get(0) !== undefined && annotationEnding.get(0) !== undefined) {
const annotationBeginning = $(
`#document-content-container span[annotation-id='${anno._id}'] .annotation-beginning-marker`,
);
const annotationEnding = $(
`#document-content-container span[annotation-id='${anno._id}'] .annotation-ending-marker`,
);
if (annotationBeginning.get(0) !== undefined
&& annotationEnding.get(0) !== undefined) {
const annotationBeginningPosition = annotationBeginning.offset();
const annotationEndingPosition = annotationEnding.offset();
h = (annotationEndingPosition.top - annotationBeginningPosition.top) + lineHeight;
} else {
h = 0;
}
}
// now we have to convert the annotations position and height into starting and ending indexs for the map
let startIndex = Math.floor((anno.position.top - offsetTop) / grandularity);
// convert the annotation position and height
// into starting and ending indexs for the map
let startIndex = Math.floor(
(anno.position.top - offsetTop) / grandularity,
);
startIndex = startIndex < 0 ? 0 : startIndex;
const endIndex = Math.floor((anno.position.top + h - offsetTop) / grandularity);
for (let i = startIndex; i <= endIndex; i += 1) {
Expand All @@ -57,8 +73,21 @@ function HeatMap({ pdf }) {

return (
<>
<div id="heat-map" style={{ height: documentHeight + (pdf ? 0 : 18) }}>
{map.map((v, i) => <div className="stroke" style={{ height: lineHeight * scaleFactor, top: i * lineHeight * scaleFactor, opacity: v * 0.5 }} />)}
<div
id="heat-map"
data-testid="heat-map"
style={{ height: documentHeight + (pdf ? 0 : 18) }}
>
{map.map((v, i) => (
<div
className="stroke"
style={{
height: lineHeight * scaleFactor,
top: i * lineHeight * scaleFactor,
opacity: v * 0.5,
}}
/>
))}
</div>

<style jsx global>
Expand All @@ -84,6 +113,6 @@ function HeatMap({ pdf }) {
</style>
</>
);
}
};

export default HeatMap;
24 changes: 24 additions & 0 deletions src/components/HeatMap/HeatMap.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @jest-environment jsdom
*/

import { render } from '@testing-library/react';
import HeatMap from './HeatMap';
import { DocumentFiltersContext, DocumentAnnotationsContext } from '../../contexts/DocumentContext';

test('renders heatmap', async () => {
const { getByTestId } = render(
<DocumentAnnotationsContext.Provider
value={[[], jest.fn(), jest.fn(), jest.fn()]}
>
<DocumentFiltersContext.Provider value={[[], jest.fn()]}>
<HeatMap
pdf={false}
/>
</DocumentFiltersContext.Provider>
</DocumentAnnotationsContext.Provider>,
);
const heatMap = getByTestId('heat-map');
expect(heatMap).toBeInTheDocument();
});

20 changes: 20 additions & 0 deletions src/components/SemanticField/SemanticField.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* @jest-environment jsdom
*/

import { render } from '@testing-library/react';
import { Formik } from 'formik';
import SemanticField from './SemanticField';

test('renders semantic field', async () => {
const { getByRole } = render(
<Formik>
<SemanticField
component="input"
type="text"
/>
</Formik>,
);
const field = getByRole('textbox');
expect(field).toBeInTheDocument();
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const SlateMediaEmbedElement = ({
title="embed"
src={`${url}`}
frameBorder="0"
data-testid="slate-iframe"
/>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* @jest-environment jsdom
*/

import { render } from '@testing-library/react';
import { Formik } from 'formik';
import SlateMediaEmbedElement from './SlateMediaEmbedElement';

test('renders slate media embed element', async () => {
const { getByTestId } = render(
<Formik>
<SlateMediaEmbedElement
element={{ url: 'https://www.youtube.com/watch?v=dGxZ4K-J5YE' }}
/>
</Formik>,
);
const elem = getByTestId('slate-iframe');
expect(elem).toBeInTheDocument();
});
43 changes: 29 additions & 14 deletions src/pages/documents/[slug]/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/* eslint-disable no-underscore-dangle */
/* eslint-disable no-restricted-syntax */
import { useState, useEffect } from 'react';
import { isMobile } from "react-device-detect"
import { isMobile } from 'react-device-detect';
import { useSession } from 'next-auth/client';
import $ from 'jquery';
import {
Expand Down Expand Up @@ -109,17 +109,18 @@ const DocumentPage = (props) => {
const [annotationChannel1Loaded, setAnnotationChannel1Loaded] = useState(false);
const [annotationChannel2Loaded, setAnnotationChannel2Loaded] = useState(false);
const minDisplayWidth = 1150;
// if true annotations will displayed in channels otherwise they will be displayed as popovers that show on hover or on click
// popovers for mobile
// eslint-disable-next-line no-unused-vars
const [displayAnnotationsInChannels, setDisplayAnnotationsInChannels] = useState(!isMobile);

const [scrollToAnnotation, setScrollToAnnotation] = useState(validQuery);

const [showMoreInfoShareModal, setShowMoreInfoShareModal] = useState();

const [session, loading] = useSession();
// the interesection between the groups that this user is in and the groups the document is shared too
// interesection between user's groups and groups the document is shared to
const [groupIntersection, setGroupIntersection] = useState();
// the people the user can share their annotations with which is generated from the groupIntersection
// other users this user can share annotations with, generated from groupIntersection
const [membersIntersection, setMembersIntersection] = useState([]);


Expand Down Expand Up @@ -381,25 +382,32 @@ const DocumentPage = (props) => {
});

useEffect(() => {
// eslint-disable-next-line no-undef
window.addEventListener('resize', () => {
// eslint-disable-next-line no-undef
setDisplayAnnotationsInChannels(window.innerWidth > minDisplayWidth && !isMobile);
});
});

async function getIntersectionOfGroupsAndUsers() {
// when the session gets loaded in we are going to get the intersection of groups and the users that applies to
if (session !== undefined && groupIntersection === undefined) { // this means we haven't set it yet
// when session loaded, get intersection of groups and the users that applies to
if (session && !groupIntersection) {
const userGroupIds = session.user.groups.map((g) => g.id);
const intersection = userGroupIds.filter((id) => document.groups.includes(id));
const intersectionGroups = await Promise.all(intersection.map((id) => getGroupById(id)));
let intersectionMembers = [];
for (let i = 0; i < intersectionGroups.length; i += 1) {
// filtering out members for this specific group that we have already included in the intersectionMembers array
const members = intersectionGroups[i].members.filter((m) => !intersectionMembers.some((im) => im.id === m.id));
// filtering out members for this specific group
// that we have already included in the intersectionMembers array
const members = intersectionGroups[i].members
// eslint-disable-next-line no-loop-func
.filter((m) => !intersectionMembers.some((im) => im.id === m.id));
intersectionMembers = intersectionMembers.concat(members);
}
// before we set the intersection of members we need to remove the id of the current user session
setMembersIntersection(intersectionMembers.filter((m) => m.id !== session.user.id).map((m) => ({ ...m, name: FirstNameLastInitial(m.name) })));
// remove id of current user session before setting intersection of members
setMembersIntersection(intersectionMembers
.filter((m) => m.id !== session.user.id)
.map((m) => ({ ...m, name: FirstNameLastInitial(m.name) })));
setGroupIntersection(intersectionGroups);
}
}
Expand All @@ -418,7 +426,9 @@ const DocumentPage = (props) => {
return (

<DocumentContext.Provider value={document}>
<DocumentAnnotationsContext.Provider value={[channelAnnotations, setChannelAnnotations, saveAnnotationChanges, getAllTags()]}>
<DocumentAnnotationsContext.Provider
value={[channelAnnotations, setChannelAnnotations, saveAnnotationChanges, getAllTags()]}
>
<DocumentFiltersContext.Provider value={[documentFilters, setDocumentFilters]}>
{!session && loading && (
<LoadingSpinner />
Expand Down Expand Up @@ -525,11 +535,16 @@ const DocumentPage = (props) => {
<p style={{ fontSize: 14 }}>
Only you can see the annotation
</p>
<p style={{ fontWeight: 600, fontSize: 16, marginBottom: 5 }}>Share with group(s)</p>
<p style={{ fontWeight: 600, fontSize: 16, marginBottom: 5 }}>
Share with group(s)
</p>
<p style={{ fontSize: 14 }}>
Share this annotation with all members of your group(s) who have access to this document.
Share this annotation with all members of
your group(s) who have access to this document.
</p>
<p style={{ fontWeight: 600, fontSize: 16, marginBottom: 5 }}>
Share with user(s)
</p>
<p style={{ fontWeight: 600, fontSize: 16, marginBottom: 5 }}>Share with user(s)</p>
<p style={{ fontSize: 14 }}>
Share this annotation with a specific user or users only.
</p>
Expand Down

0 comments on commit 0fe950e

Please sign in to comment.