-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: improve publication page (#1238)
- feat: add component test to the project - feat: update notifier to enable or not the notifications
- Loading branch information
Showing
87 changed files
with
5,274 additions
and
1,545 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import DebouncedTextField, { | ||
DEBOUNCE_MS, | ||
} from '@/components/input/DebouncedTextField'; | ||
import { DEBOUNCED_TEXT_FIELD_ID } from '@/config/selectors'; | ||
|
||
const ON_UPDATE_SPY = 'onUpdate'; | ||
const getSpyOnUpdate = () => `@${ON_UPDATE_SPY}`; | ||
const eventHandler = { | ||
onUpdate: (_newValue: string) => {}, | ||
}; | ||
const LABEL = 'Label'; | ||
const VALUE = 'My value'; | ||
|
||
const getTextArea = () => cy.get(`#${DEBOUNCED_TEXT_FIELD_ID}`); | ||
|
||
describe('<DebouncedTextField />', () => { | ||
beforeEach(() => { | ||
cy.spy(eventHandler, 'onUpdate').as(ON_UPDATE_SPY); | ||
}); | ||
|
||
describe('Value is defined', () => { | ||
beforeEach(() => { | ||
cy.mount( | ||
<DebouncedTextField | ||
initialValue={VALUE} | ||
label={LABEL} | ||
onUpdate={eventHandler.onUpdate} | ||
/>, | ||
); | ||
}); | ||
it('Initial value should not called onUpdate', () => { | ||
getTextArea().should('be.visible'); | ||
cy.get(getSpyOnUpdate()).should('not.be.called'); | ||
}); | ||
|
||
it('Edit value should be called onUpdate', () => { | ||
const NEW_VALUE = 'My new value'; | ||
getTextArea().clear().type(NEW_VALUE); | ||
|
||
cy.get(getSpyOnUpdate()).should('be.calledOnceWith', NEW_VALUE); | ||
}); | ||
|
||
it('Edit value multiple times should debounce onUpdate', () => { | ||
const NEW_VALUE = 'My new value'; | ||
getTextArea().clear().type(NEW_VALUE); | ||
|
||
// Write again before the end of the debounce timeout | ||
const APPEND_VALUE = ' which has been debounced'; | ||
cy.wait(DEBOUNCE_MS - 100); | ||
getTextArea().type(APPEND_VALUE); | ||
cy.get(getSpyOnUpdate()).should( | ||
'be.calledOnceWith', | ||
`${NEW_VALUE}${APPEND_VALUE}`, | ||
); | ||
}); | ||
}); | ||
|
||
describe('Can not be empty if not allowed', () => { | ||
beforeEach(() => { | ||
cy.mount( | ||
<DebouncedTextField | ||
initialValue={VALUE} | ||
label={LABEL} | ||
onUpdate={eventHandler.onUpdate} | ||
required | ||
/>, | ||
); | ||
}); | ||
|
||
it('Empty value should not call onUpdate if not allowed', () => { | ||
getTextArea().clear(); | ||
cy.get(getSpyOnUpdate()).should('not.be.called'); | ||
}); | ||
|
||
it('onUpdate should be called if value is not empty', () => { | ||
const NEW_VALUE = 'My new value'; | ||
getTextArea().clear().type(NEW_VALUE); | ||
cy.get(getSpyOnUpdate()).should('be.calledOnceWith', NEW_VALUE); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
import MultiSelectChipInput from '@/components/input/MultiSelectChipInput'; | ||
import { | ||
MULTI_SELECT_CHIP_ADD_BUTTON_ID, | ||
MULTI_SELECT_CHIP_CONTAINER_ID, | ||
MULTI_SELECT_CHIP_INPUT_ID, | ||
buildDataCyWrapper, | ||
buildMultiSelectChipsSelector, | ||
} from '@/config/selectors'; | ||
|
||
const ON_SAVE_SPY = 'onSave'; | ||
const getSpyOnSave = () => `@${ON_SAVE_SPY}`; | ||
const eventHandler = { onSave: (_values: string[]) => {} }; | ||
const EXISTING_VALUES = ['first', 'second', 'third']; | ||
const NEW_VALUE = 'my new value'; | ||
const LABEL = 'my label'; | ||
|
||
const getInput = () => | ||
cy.get(`${buildDataCyWrapper(MULTI_SELECT_CHIP_INPUT_ID)} input`); | ||
|
||
const addANewValue = (newValue: string) => { | ||
getInput().type(newValue); | ||
cy.get(buildDataCyWrapper(MULTI_SELECT_CHIP_ADD_BUTTON_ID)).click(); | ||
}; | ||
|
||
const removeAValue = (valueToRemove: string) => { | ||
const idxOfRemovedValue = EXISTING_VALUES.findIndex( | ||
(value) => value === valueToRemove, | ||
); | ||
|
||
if (idxOfRemovedValue === -1) { | ||
throw new Error(`Given value to remove "${valueToRemove}" was not found!`); | ||
} | ||
|
||
cy.get( | ||
`${buildDataCyWrapper(buildMultiSelectChipsSelector(idxOfRemovedValue))} svg`, | ||
).click(); | ||
}; | ||
|
||
describe('<MultiSelectChipInput />', () => { | ||
beforeEach(() => { | ||
cy.spy(eventHandler, 'onSave').as(ON_SAVE_SPY); | ||
}); | ||
|
||
describe('Data is empty', () => { | ||
beforeEach(() => { | ||
cy.mount( | ||
<MultiSelectChipInput | ||
data={[]} | ||
onSave={eventHandler.onSave} | ||
label={LABEL} | ||
/>, | ||
); | ||
}); | ||
|
||
it('Chips container should not exist when no data', () => { | ||
cy.get(buildDataCyWrapper(MULTI_SELECT_CHIP_CONTAINER_ID)).should( | ||
'not.exist', | ||
); | ||
}); | ||
|
||
it('Add a new value should add a new chip', () => { | ||
addANewValue(NEW_VALUE); | ||
cy.get(buildDataCyWrapper(MULTI_SELECT_CHIP_CONTAINER_ID)) | ||
.children() | ||
.should('have.length', 1) | ||
.should('contain', NEW_VALUE); | ||
}); | ||
|
||
it('Add a new value should reset current value', () => { | ||
addANewValue(NEW_VALUE); | ||
getInput().should('have.value', ''); | ||
}); | ||
|
||
it('Add a new empty value should not be possible', () => { | ||
getInput().should('have.value', ''); | ||
cy.get(buildDataCyWrapper(MULTI_SELECT_CHIP_ADD_BUTTON_ID)).should( | ||
'be.disabled', | ||
); | ||
}); | ||
}); | ||
|
||
describe('Have some data', () => { | ||
const valueToRemove = EXISTING_VALUES[1]; | ||
|
||
beforeEach(() => { | ||
cy.mount( | ||
<MultiSelectChipInput | ||
onSave={eventHandler.onSave} | ||
data={EXISTING_VALUES} | ||
label={LABEL} | ||
/>, | ||
); | ||
}); | ||
|
||
it('Chips container should contains existing chips', () => { | ||
cy.get(buildDataCyWrapper(MULTI_SELECT_CHIP_CONTAINER_ID)) | ||
.children() | ||
.should('have.length', EXISTING_VALUES.length); | ||
}); | ||
|
||
it('Add a new value should add a new chip', () => { | ||
addANewValue(NEW_VALUE); | ||
cy.get(buildDataCyWrapper(MULTI_SELECT_CHIP_CONTAINER_ID)) | ||
.children() | ||
.should('have.length', EXISTING_VALUES.length + 1) | ||
.should('contain', NEW_VALUE); | ||
}); | ||
|
||
it('Add a new value should call onSave', () => { | ||
addANewValue(NEW_VALUE); | ||
cy.get(getSpyOnSave()).should('be.calledWith', [ | ||
...EXISTING_VALUES, | ||
NEW_VALUE, | ||
]); | ||
}); | ||
|
||
it('Add an existing value should not be possible', () => { | ||
getInput().type(EXISTING_VALUES[0].toUpperCase()); | ||
cy.get(buildDataCyWrapper(MULTI_SELECT_CHIP_ADD_BUTTON_ID)).should( | ||
'be.disabled', | ||
); | ||
}); | ||
|
||
it('Add an existing value should not call onSave', () => { | ||
getInput().type(EXISTING_VALUES[0].toUpperCase()); | ||
cy.get(getSpyOnSave()).should('not.be.called'); | ||
}); | ||
|
||
it('Remove a value should remove the chip', () => { | ||
removeAValue(valueToRemove); | ||
cy.get(buildDataCyWrapper(MULTI_SELECT_CHIP_CONTAINER_ID)) | ||
.children() | ||
.should('have.length', EXISTING_VALUES.length - 1) | ||
.should('not.contain', valueToRemove); | ||
}); | ||
|
||
it('Remove a value should call onSave', () => { | ||
removeAValue(valueToRemove); | ||
cy.get(getSpyOnSave()).should( | ||
'be.calledWith', | ||
EXISTING_VALUES.filter((e) => e !== valueToRemove), | ||
); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.