Merge branch 'VRFS-5232-new_react_frontend' of https://bitbucket.org/jamkazam/jam-cloud into VRFS-5232-new_react_frontend

This commit is contained in:
Victor Barba Martin 2021-10-19 22:12:07 +02:00
commit e26b713943
6 changed files with 272 additions and 147 deletions

View File

@ -2,27 +2,25 @@
describe('Friends page without data', () => {
beforeEach(() => {
cy.stubAuthenticate();
cy.intercept('POST', /\S+\/filter/,
{
"musicians": []
}
);
})
cy.stubAuthenticate();
cy.intercept('POST', /\S+\/filter/, {
musicians: []
});
});
it('shows no records alert', () => {
cy.visit('/friends');
cy.contains('No Records!')
})
})
cy.contains('No Records!');
});
});
describe('Friends page with data', () => {
beforeEach(() => {
cy.stubAuthenticate({ id: '2'}); //currentUser id is 2 - people.yaml fixture
cy.intercept('POST', /\S+\/filter/, { fixture: 'people' });
cy.stubAuthenticate({ id: '2' }); //currentUser id is 2 - people.yaml fixture
cy.intercept('POST', /\S+\/filter/, { fixture: 'people' }).as('getPeople');
});
describe('friends list', () => {
describe('listing users', () => {
beforeEach(() => {
cy.visit('/friends');
});
@ -40,80 +38,79 @@ describe('Friends page with data', () => {
//TODO: paginate
});
describe('details side panel', () => {
describe('user details side panel', () => {
const showSidePanelContent = () => {
cy.get('[data-testid=profileSidePanel] h4').should('have.text', 'Test User1')
cy.get('[data-testid=profileSidePanel] h4').should('have.text', 'Test User1');
cy.get('[data-testid=profileSidePanel] .modal-body p').within(() => {
cy.contains('Location: Denver, US')
.and('contain', 'Location: Denver, US')
.and('contain', 'Skill Level: Professional')
.and('contain', 'Joined JamKazam: 08-26-2021')
.and('contain', 'Last Active:')
.and('contain', 'Latency to Me:')
cy.get('.latency-badge').contains('UNKNOWN')
})
.and('contain', 'Location: Denver, US')
.and('contain', 'Skill Level: Professional')
.and('contain', 'Joined JamKazam: 08-26-2021')
.and('contain', 'Last Active:')
.and('contain', 'Latency to Me:');
cy.get('.latency-badge').contains('UNKNOWN');
});
cy.get('[data-testid=profileSidePanel] .modal-body').within(() => {
cy.get('[data-testid=biography]').contains('Biography of Test User1')
cy.get('[data-testid=biography]').contains('Biography of Test User1');
//instruments
cy.get('[data-testid=instruments]').contains('Acoustic Guitar: Expert')
cy.get('[data-testid=instruments]').contains('Keyboard: Expert')
cy.get('[data-testid=instruments]').contains('Acoustic Guitar: Expert');
cy.get('[data-testid=instruments]').contains('Keyboard: Expert');
//genres
cy.get('[data-testid=genres]').contains('classical, blues')
cy.get('[data-testid=genres]').contains('classical, blues');
//bands
cy.get('[data-testid=bands]').contains('The Band')
cy.get('[data-testid=bands]').contains('The Band');
//performance_samples
//cy.get('[data-testid=performance_samples]').contains('The Band')
//online presence
cy.get('[data-testid=online_presences]')
.contains('Soundcloud')
cy.get('[data-testid=online_presences]')
.contains('Reverbnation')
})
}
cy.get('[data-testid=online_presences]').contains('Soundcloud');
cy.get('[data-testid=online_presences]').contains('Reverbnation');
});
};
const closeMoreDetailsSidePanel = () => {
cy.get('[data-testid=profileSidePanel] .modal-header button.close').click()
}
beforeEach(() => {
cy.get('[data-testid=profileSidePanel] .modal-header button.close').click();
};
beforeEach(() => {
cy.intercept('GET', /\S+\/profile\S+/, { fixture: 'person' });
cy.visit('/friends');
cy.visit('/friends');
});
it('shows profile side panel', () => {
//open side panel by clicking name
cy.contains('Test User1').click();
showSidePanelContent()
closeMoreDetailsSidePanel()
showSidePanelContent();
closeMoreDetailsSidePanel();
//open side panel by clicking more button
cy.get('[data-testid=peopleListTable] > tbody tr').first().find('[data-testid=btnMore]').click()
showSidePanelContent()
closeMoreDetailsSidePanel()
cy.get('[data-testid=peopleListTable] > tbody tr')
.first()
.find('[data-testid=btnMore]')
.click();
showSidePanelContent();
closeMoreDetailsSidePanel();
//open side panel by clicking more link
cy.get('[data-testid=peopleListTable] > tbody tr').first().find('[data-testid=linkMore]').click()
showSidePanelContent()
closeMoreDetailsSidePanel()
cy.get('[data-testid=peopleListTable] > tbody tr')
.first()
.find('[data-testid=linkMore]')
.click();
showSidePanelContent();
closeMoreDetailsSidePanel();
});
});
describe('making friendship', () => {
it('add friend', () => {
cy.intercept('GET', /\S+\/profile\S+/, { fixture: 'person' });
cy.intercept('POST', /\S+\/friend_requests/, { statusCode: 201, body: { ok: true } });
cy.visit('/friends');
cy.contains('Test User1').click();
@ -124,7 +121,7 @@ describe('Friends page with data', () => {
cy.get('[data-testid=profileSidePanel]')
.find('[data-testid=connect]')
.should('be.disabled');
cy.contains('Friend request was sent')
cy.contains('Friend request was sent');
});
it('remove friend', () => {
@ -147,107 +144,224 @@ describe('Friends page with data', () => {
cy.get('[data-testid=profileSidePanel]')
.find('[data-testid=connect]')
.should('be.exist')
.should('not.be.disabled')
.should('not.be.disabled');
});
})
});
describe('chat window', () => {
beforeEach(() => {
cy.visit('/friends');
});
it('is not disabled for friends', () => {
cy.get('[data-testid=peopleListTable] > tbody tr')
.eq(0)
.find('[data-testid=message]').should('not.be.disabled').trigger('mouseover')
cy.contains('Send a message').should('exist')
})
.eq(0)
.find('[data-testid=message]')
.should('not.be.disabled')
.trigger('mouseover');
cy.contains('Send a message').should('exist');
});
it('is disabled for non friends', () => {
cy.get('[data-testid=peopleListTable] > tbody tr')
.eq(1)
.find('[data-testid=message]').should('be.disabled')
.eq(1)
.find('[data-testid=message]')
.should('be.disabled');
//cy.contains('You can message this user once you are friends').should('exist')
})
});
it('lists text messages', () => {
//initially show the most recent messages on openning chat window modal
let numberOfMessages = 10
cy.fixture('text_messages_page1').then((json) => {
let numberOfMessages = 10;
cy.fixture('text_messages_page1').then(json => {
cy.intercept('GET', /\S+\/text_messages\S+/, json).as('getTextMessages');
})
});
cy.get('[data-testid=peopleListTable] > tbody tr')
.eq(0)
.find('[data-testid=message]').click()
cy.wait('@getTextMessages')
cy.get('[data-testid=textMessageModal]').should('be.visible').within(() => {
cy.get('.text-message-row').should('have.length', numberOfMessages)
//display previous messages by scrolling up
const messageFixtures = [
'text_messages_page2',
'text_messages_page3'
]
messageFixtures.forEach((fixture) => {
cy.fixture(fixture).then((json) => {
cy.intercept('GET', /\S+\/text_messages\S+/, json)
cy.get('.modal-body .ScrollbarsCustom').trigger('mouseover').scrollTo('bottom')
cy.get('.modal-body .ScrollbarsCustom').trigger('mouseover').scrollTo('top')
numberOfMessages = numberOfMessages + 10
cy.get('.text-message-row').should('have.length', numberOfMessages)
})
})
cy.get('button').contains('Close').should('not.be.disabled').click()
.eq(0)
.find('[data-testid=message]')
.click();
cy.wait('@getTextMessages');
cy.get('[data-testid=textMessageModal]')
.should('be.visible')
.within(() => {
cy.get('.text-message-row').should('have.length', numberOfMessages);
})
cy.get('[data-testid=textMessageModal]').should('not.be.visible')
//display previous messages by scrolling up
const messageFixtures = ['text_messages_page2', 'text_messages_page3'];
messageFixtures.forEach(fixture => {
cy.fixture(fixture).then(json => {
cy.intercept('GET', /\S+\/text_messages\S+/, json);
cy.get('.modal-body .ScrollbarsCustom')
.trigger('mouseover')
.scrollTo('bottom');
cy.get('.modal-body .ScrollbarsCustom')
.trigger('mouseover')
.scrollTo('top');
numberOfMessages = numberOfMessages + 10;
cy.get('.text-message-row').should('have.length', numberOfMessages);
});
});
cy.get('button')
.contains('Close')
.should('not.be.disabled')
.click();
});
cy.get('[data-testid=textMessageModal]').should('not.be.visible');
});
})
it('sends message by clicking send button', () => {
cy.get('[data-testid=peopleListTable] > tbody tr')
.eq(0)
.find('[data-testid=message]').click()
.eq(0)
.find('[data-testid=message]')
.click();
cy.get('[data-testid=textMessageModal]').within(() => {
cy.get('button').contains('Send').should('be.disabled')
cy.get('textarea').type('Hello')
cy.get('button').contains('Send').should('not.be.disabled').click()
cy.get('textarea').should('have.value', '')
cy.get('button').contains('Send').should('be.disabled')
})
})
cy.get('button')
.contains('Send')
.should('be.disabled');
cy.get('textarea').type('Hello');
cy.get('button')
.contains('Send')
.should('not.be.disabled')
.click();
cy.get('textarea').should('have.value', '');
cy.get('button')
.contains('Send')
.should('be.disabled');
});
});
it('sends message by pressing enter key', () => {
cy.get('[data-testid=peopleListTable] > tbody tr')
.eq(0)
.find('[data-testid=message]').click()
.eq(0)
.find('[data-testid=message]')
.click();
cy.get('[data-testid=textMessageModal]').within(() => {
cy.get('button').contains('Send').should('be.disabled')
cy.get('textarea').type('Hello{enter}')
cy.get('textarea').should('have.value', '')
cy.get('button').contains('Send').should('be.disabled')
})
})
cy.get('button')
.contains('Send')
.should('be.disabled');
cy.get('textarea').type('Hello{enter}');
cy.get('textarea').should('have.value', '');
cy.get('button')
.contains('Send')
.should('be.disabled');
});
});
it('goes away by clicking close button', () => {
cy.get('[data-testid=peopleListTable] > tbody tr')
.eq(0)
.find('[data-testid=message]').click()
.eq(0)
.find('[data-testid=message]')
.click();
cy.get('[data-testid=textMessageModal]').within(() => {
cy.get('button').contains('Close').should('not.be.disabled').click()
})
cy.get('[data-testid=textMessageModal]').should('not.be.visible')
})
cy.get('button')
.contains('Close')
.should('not.be.disabled')
.click();
});
cy.get('[data-testid=textMessageModal]').should('not.be.visible');
});
it.skip('shows received message by other user', () => {
//TODO: this should be test in e2e test
});
});
describe('filter', () => {
const fillFilterForm = () => {
//cy.get('[data-testid=btnUpdateSearch]').click();
cy.get('[data-testid=modalUpdateSearch] input[name=latency_good]').uncheck();
cy.get('[data-testid=modalUpdateSearch] input[name=latency_fair]').uncheck();
cy.get('[data-testid=modalUpdateSearch] input[name=latency_high]').uncheck();
cy.get('[data-testid=modalUpdateSearch] input[name=proficiency_beginner]').uncheck();
cy.get('[data-testid=modalUpdateSearch] input[name=proficiency_intermediate]').uncheck();
cy.get('[data-testid=modalUpdateSearch] input[name=proficiency_expert]').uncheck();
cy.get('[data-testid=modalUpdateSearch] input[name=proficiency_expert]').uncheck();
cy.get('#selInstruments')
.type('Drums{enter}')
.click();
cy.get('#selGenres')
.type('Pop{enter}')
.click();
cy.get('#selLastActive').type('Within last 1 Day{enter}');
cy.get('#selJoinedWithin').type('Within last 7 Day{enter}');
}
beforeEach(() => {
cy.visit('/friends');
});
it('open and close filter modal', () => {
cy.get('[data-testid=btnUpdateSearch]').click();
cy.get('[data-testid=modalUpdateSearch]').should('be.visible');
cy.get('[data-testid=modalUpdateSearch]')
.contains('Cancel')
.click();
cy.get('[data-testid=modalUpdateSearch]').should('not.be.visible');
});
it('reset filters', () => {
cy.get('[data-testid=btnUpdateSearch]').click();
fillFilterForm()
cy.get('[data-testid=modalUpdateSearch]')
.contains('Cancel')
.click();
cy.get('[data-testid=btnUpdateSearch]').click();
cy.get('[data-testid=modalUpdateSearch] input[name=latency_good]').should('not.be.checked')
cy.get('[data-testid=modalUpdateSearch]')
.contains('Cancel')
.click();
cy.get('[data-testid=btnResetSearch]').click() //click reset button
cy.get('[data-testid=btnUpdateSearch]').click();
cy.get('[data-testid=modalUpdateSearch] input[name=latency_good]').should('be.checked')
})
})
it('submit filter form with params', () => {
//wait for stubbed request sent to fetch data for initial page load
cy.wait('@getPeople').then(interception => {
assert.isNotNull(interception.response.body, '1st API call has data');
});
cy.get('[data-testid=btnUpdateSearch]').click();
cy.get('[data-testid=btnSubmitSearch]').click();
//wait for stubbed request sent by submitting search form without filling any form field
cy.wait('@getPeople')
.then(interception => {
assert.isNotNull(interception.response.body, '2nd API call has data');
})
.its('request.body')
.should('deep.equal', {
latency_good: true,
latency_fair: true,
latency_high: true,
proficiency_beginner: true,
proficiency_intermediate: true,
proficiency_expert: true,
instruments: [],
genres: []
});
cy.get('[data-testid=btnUpdateSearch]').click();
fillFilterForm()
cy.get('[data-testid=btnSubmitSearch]').click();
//wait for stubbed request sent by submitting search form again. but this time fill form fields
cy.wait('@getPeople')
.then(interception => {
assert.isNotNull(interception.response.body, '3rd API call has data');
})
.its('request.body')
.should('deep.equal', {
latency_good: false,
latency_fair: false,
latency_high: false,
proficiency_beginner: false,
proficiency_intermediate: false,
proficiency_expert: false,
instruments: [{ value: 'drums', label: 'Drums' }],
genres: ['pop'],
active_within_days: '1',
joined_within_days: '7'
});
});
});
});

View File

@ -10,7 +10,7 @@ describe("Top Navigation", () => {
const showProfileDropdown = () => {
cy.get('[data-testid=navbarTopProfileDropdown]').should('exist')
cy.contains("Peter Pan").should('exist')
cy.contains("My Profile").should('exist')
//cy.contains("My Profile").should('exist')
cy.contains("Sign out").should('exist')
}

View File

@ -16,6 +16,7 @@
// Import commands.js using ES2015 syntax:
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')

View File

@ -15,6 +15,7 @@ import JKPeopleSwiper from './JKPeopleSwiper';
const JKPeople = ({ className }) => {
const [showSearch, setShowSearch] = useState(false);
const [page, setPage] = useState(1);
const [resetFilter, setResetFilter] = useState(false)
const peopleListRef = useRef();
const dispatch = useDispatch();
@ -62,6 +63,8 @@ const JKPeople = ({ className }) => {
}
};
useEffect(() => {
window.addEventListener('scroll', handleScroll, { passive: true });
return () => {
@ -71,16 +74,16 @@ const JKPeople = ({ className }) => {
return (
<Card>
<JKPeopleSearch show={showSearch} setShow={setShowSearch} />
<JKPeopleSearch show={showSearch} setShow={setShowSearch} resetFilter={resetFilter} setResetFilter={setResetFilter} />
<FalconCardHeader
title={`Find New Friends`}
titleClass="font-weight-bold"
>
<Form inline className="mt-md-0 mt-3">
<Button color="primary" className="me-2 mr-2 fs--1" onClick={() => setShowSearch(!showSearch)}>
<Button color="primary" className="me-2 mr-2 fs--1" onClick={() => setShowSearch(!showSearch)} data-testid="btnUpdateSearch">
Update Search
</Button>
<Button outline disabled color="secondary" className="fs--1">
<Button outline color="secondary" className="fs--1" data-testid="btnResetSearch" onClick={() => setResetFilter(true)}>
Reset Filters
</Button>
</Form>

View File

@ -1,21 +1,21 @@
import React, { useState, useEffect, useRef, Fragment } from 'react';
import React, { useState, useEffect } from 'react';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import Select from 'react-select';
import JKTooltip from '../common/JKTooltip';
import PropTypes from 'prop-types';
import { getGenres, getInstruments } from '../../helpers/rest';
import { useForm, Controller } from 'react-hook-form';
import { useForm, Controller, useFormState } from 'react-hook-form';
import { useDispatch } from 'react-redux';
import { fetchPeople } from '../../store/features/peopleSlice';
const JKPeopleSearch = props => {
const { show, setShow } = props;
const { show, setShow, resetFilter, setResetFilter } = props;
const [instruments, setInstruments] = useState([]);
const [genres, setGenres] = useState([]);
const dispatch = useDispatch();
const { register, handleSubmit, setValue, control } = useForm({
const { register, handleSubmit, setValue, control, reset } = useForm({
defaultValues: {
latency_good: true,
latency_fair: true,
@ -26,10 +26,11 @@ const JKPeopleSearch = props => {
instruments: [],
joined_within_days: '-1',
active_within_days: '-1'
}
});
const {isDirty} = useFormState({control});
const toggle = () => setShow(!show);
const fetchInstruments = async () => {
@ -76,13 +77,19 @@ const JKPeopleSearch = props => {
});
};
useEffect(() => {
if(resetFilter){
reset()
setResetFilter(false)
}
}, [resetFilter])
useEffect(() => {
fetchGenres();
fetchInstruments();
}, []);
const submitForm = event => {
console.log('submitForm');
event.preventDefault();
handleSubmit(onSubmit)();
setShow(false);
@ -125,8 +132,8 @@ const JKPeopleSearch = props => {
];
return (
<Fragment>
<Modal isOpen={show} toggle={toggle} className="mw-100 mx-1 mr-1 ml-1 mx-md-5 mr-md-5 ml-md-5 mx-xl-10 mr-xl-10 ml-xl-10">
<Modal isOpen={show} toggle={toggle} className="mw-100 mx-1 mr-1 ml-1 mx-md-5 mr-md-5 ml-md-5 mx-xl-10 mr-xl-10 ml-xl-10" data-testid="modalUpdateSearch">
<ModalHeader toggle={toggle}>Update Search</ModalHeader>
<ModalBody>
<div className="px-4 pb-4">
@ -145,7 +152,7 @@ const JKPeopleSearch = props => {
{...register('latency_good')}
type="checkbox"
className="form-check-input"
defaultChecked
defaultChecked={!isDirty}
onChange={e => setValue('latency_good', e.target.checked)}
/>
<label className="form-check-label">Good (40ms or less)</label>
@ -155,7 +162,7 @@ const JKPeopleSearch = props => {
{...register('latency_fair')}
type="checkbox"
className="form-check-input"
defaultChecked
defaultChecked={!isDirty}
onChange={e => setValue('latency_fair', e.target.checked)}
/>
<label className="form-check-label">Fair (41-80ms)</label>
@ -165,7 +172,7 @@ const JKPeopleSearch = props => {
{...register('latency_high')}
type="checkbox"
className="form-check-input"
defaultChecked
defaultChecked={!isDirty}
onChange={e => setValue('latency_high', e.target.checked)}
/>
<label className="form-check-label">High (81ms +)</label>
@ -181,7 +188,7 @@ const JKPeopleSearch = props => {
{...register('proficiency_beginner')}
type="checkbox"
className="form-check-input"
defaultChecked
defaultChecked={!isDirty}
onChange={e => setValue('proficiency_beginner', e.target.checked)}
/>
<label className="form-check-label">Beginner</label>
@ -191,7 +198,7 @@ const JKPeopleSearch = props => {
{...register('proficiency_intermediate')}
type="checkbox"
className="form-check-input"
defaultChecked
defaultChecked={!isDirty}
onChange={e => setValue('proficiency_intermediate', e.target.checked)}
/>
<label className="form-check-label">Intermediate</label>
@ -201,7 +208,7 @@ const JKPeopleSearch = props => {
{...register('proficiency_expert')}
type="checkbox"
className="form-check-input"
defaultChecked
defaultChecked={!isDirty}
onChange={e => setValue('proficiency_expert', e.target.checked)}
/>
<label className="form-check-label">Expert</label>
@ -221,7 +228,7 @@ const JKPeopleSearch = props => {
name="instruments"
control={control}
render={({ field }) => (
<Select {...field} options={instruments} isMulti closeMenuOnSelect={false} />
<Select {...field} options={instruments} isMulti closeMenuOnSelect={false} id="selInstruments" />
)}
/>
</div>
@ -234,7 +241,7 @@ const JKPeopleSearch = props => {
name="genres"
control={control}
render={({ field }) => (
<Select {...field} options={genres} isMulti closeMenuOnSelect={false} />
<Select {...field} options={genres} isMulti closeMenuOnSelect={false} id="selGenres" />
)}
/>
</div>
@ -246,7 +253,7 @@ const JKPeopleSearch = props => {
name="active_within_days"
control={control}
render={({ field }) => (
<Select {...field } options={lastActiveOpts} />
<Select {...field } options={lastActiveOpts} id="selLastActive" />
)}
/>
</div>
@ -258,7 +265,7 @@ const JKPeopleSearch = props => {
name="joined_within_days"
control={control}
render={({ field}) => (
<Select {...field} options={joinedOpts} />
<Select {...field} options={joinedOpts} id="selJoinedWithin" />
)}
/>
</div>
@ -271,12 +278,12 @@ const JKPeopleSearch = props => {
<Button color="outline-primary" onClick={toggle}>
Cancel
</Button>{' '}
<Button color="primary" onClick={submitForm}>
Update Search
<Button color="primary" onClick={submitForm} data-testid="btnSubmitSearch">
Search
</Button>
</ModalFooter>
</Modal>
</Fragment>
);
};

View File

@ -1,4 +1,4 @@
export const version = '2.10.2';
export const version = '0.0.1';
export const navbarBreakPoint = 'xl'; // Vertical navbar breakpoint
export const topNavbarBreakpoint = 'lg';
export const settings = {