Skip to content

Commit

Permalink
Merge pull request #438 from masakudamatsu/tiptap
Browse files Browse the repository at this point in the history
Use Tiptap for text editor in place of Slate.js
  • Loading branch information
masakudamatsu authored Apr 4, 2023
2 parents d6f309e + 7c599d6 commit 43c8314
Show file tree
Hide file tree
Showing 25 changed files with 2,441 additions and 768 deletions.
1 change: 1 addition & 0 deletions cypress/e2e/all.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import './auth.cy';
import './background.cy';
import './editor.cy';
import './geolocation.cy';
import './landmarks.cy';
import './menu.cy';
Expand Down
33 changes: 33 additions & 0 deletions cypress/e2e/editor.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {buttonLabel} from '../../src/utils/uiCopies';

const placeName = '出逢ひ茶屋おせん';
describe('Editor feature', () => {
beforeEach(() => {
cy.log('Resetting the database');
cy.exec('npx prisma migrate reset --force'); // https://docs.cypress.io/guides/end-to-end-testing/testing-your-app#Seeding-data
cy.log('Setting up');
cy.auth('subscribed_user2', {
username: Cypress.env('auth0UserSubscribed2'),
password: Cypress.env('auth0PassSubscribed2'),
});
cy.visit('/');
cy.waitForMapToLoad();
cy.log('Opening the editor');
cy.findByRole('button', {name: placeName}).click();
cy.findByRole('button', {name: buttonLabel.edit}).click();
});
it(`Saving a note without place name will show 'Unnamed place' as place name`, () => {
cy.log('Preparing for deleting the whole place name');
const del = '{del}';
let keystroke = '';
for (let i = 0; i < placeName.length; i++) {
keystroke = del + keystroke;
}
cy.log('Deleting place name and saving the note...');
cy.findByRole('textbox').type(keystroke);
cy.findByText(placeName).should('not.exist'); // verify if above commands work
cy.findByRole('button', {name: buttonLabel.saveEdit}).click();
cy.log(`...shows 'Unnamed place' as its place name`);
cy.findByText('Unnamed place').should('be.visible');
});
});
47 changes: 44 additions & 3 deletions cypress/e2e/saved-places.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,27 @@ describe('Saved place detail feature', () => {
cy.findByRole('heading', {name: editorLabel, timeout: 20000}).should(
'be.visible',
);
cy.log(`...autofocuses the note field`);
cy.log(`...autofocuses the note`);
cy.focused().should('have.attr', 'role', 'textbox');
cy.log(
`...tells screen readers that pressing the Enter key will insert a line break, not submit the entered text`,
);
cy.focused().should('have.attr', 'aria-multiline', 'true');

cy.log(`Typing text...`);
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(100); // otherwise, Cypress will type 'bc', not 'abc'. This is a known issue. See https://www.cypress.io/blog/2019/01/22/when-can-the-test-click/
cy.findByRole('textbox').type('abc ');
cy.log(`...updates the place name*`);
cy.findByRole('textbox').get('h2').contains('abc', {timeout: 20000});
cy.findByRole('heading', {level: 2}).should('include.text', 'abc', {
timeout: 20000,
});

cy.log(`Pressing Down Arrow key and typing URL text...`);
cy.findByRole('textbox').type('{downarrow}');
cy.focused().type('https://google.com ');
cy.log(`...updates the place note`);
cy.findByRole('textbox').get('p').contains('https://google.com');
cy.contains('https://google.com').should('be.visible');

cy.log(`Clicking Save button...`);
cy.findByRole('button', {name: buttonLabel.saveEdit}).click();
Expand Down Expand Up @@ -232,3 +238,38 @@ describe('Saved place detail feature', () => {
cy.focused().contains(buttonLabel.delete);
});
});
describe('Edge cases', () => {
beforeEach(() => {
cy.log('Resetting the database');
cy.exec('npx prisma migrate reset --force'); // https://docs.cypress.io/guides/end-to-end-testing/testing-your-app#Seeding-data
cy.log('Setting up');
cy.auth();
cy.visit('/');
cy.waitForMapToLoad();
});
it.skip('Searching a place just deleted will drop a place mark and show its detail', () => {
// TODO #428: Fix this test
cy.log(`Setup: Saving a place`);
const savedPlaceName = 'Kyoto Station';
cy.findByRole('button', {name: buttonLabel.search}).click();
cy.focused().realType(savedPlaceName);
cy.findByRole('option', {name: savedPlaceName})
.should('be.visible')
.click(); // This fails...
cy.findByRole('button', {name: buttonLabel.saveSearchedPlace}).click();
cy.findByRole('button', {name: buttonLabel.saveEdit}).click();
cy.log(`Setup: Deleting a place`);
cy.findByRole('button', {name: savedPlaceName}).click();
cy.findByRole('button', {name: buttonLabel.delete}).click();
cy.findByRole('button', {name: buttonLabel.delete}).click();
cy.log(`Execute: Searching for the place just deleted...`);
cy.findByRole('button', {name: buttonLabel.search}).click();
cy.focused().realType(savedPlaceName);
cy.findByRole('option', {name: savedPlaceName})
.should('be.visible')
.click(); // This fails...
cy.log('Verify: ...Shows the place on the map');
cy.findByRole('button', {name: savedPlaceName}).should('be.visible');
cy.findByRole('heading', {name: savedPlaceName}).should('be.visible');
});
});
8 changes: 7 additions & 1 deletion cypress/e2e/saving-a-place.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ describe('Saving feature', () => {
cy.log('Clicking the save button on the searched place detail popup');
cy.findByRole('button', {name: buttonLabel.saveSearchedPlace}).click();
cy.log('...shows the text editor');
cy.findByRole('form', {name: editorLabel}).should('be.visible'); // see https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/form_role#description
cy.findByRole('heading', {name: editorLabel}).should('be.visible');
cy.findByRole('textbox').contains(searchedPlace.name);
cy.findByRole('textbox').contains(searchedPlace.address);
Expand Down Expand Up @@ -68,10 +69,15 @@ describe('Saving feature', () => {
cy.log('...shows link text');
cy.findByRole('link', {name: linkText.searchedPlace})
.should('have.attr', 'target', '_blank')
.should('have.attr', 'rel', 'noreferrer')
.should('have.attr', 'rel', 'nofollow noreferrer')
.then(link => {
cy.request(link.prop('href')).its('status').should('eq', 200);
});
cy.log('...allows user to close the popup');
cy.findByRole('button', {name: buttonLabel.closePlaceDetail}).click();
cy.findByRole('heading', {name: searchedPlace.name}).should(
'not.exist',
);
});
});
it('cancel button', () => {
Expand Down
164 changes: 115 additions & 49 deletions cypress/e2e/search.cy.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import {buttonLabel, linkText, searchBoxLabel} from '../../src/utils/uiCopies';
import {interceptIndefinitely} from '../../test/utils/cypress';
import {
buttonLabel,
errorMessage,
linkText,
loadingMessage,
searchBoxLabel,
} from '../../src/utils/uiCopies';
import {
boldText,
minPopupWidth,
Expand Down Expand Up @@ -52,6 +59,10 @@ describe('Place search feature', () => {
cy.findByRole('combobox').should('be.visible'); // Wait for search box module to be loaded; Cypress may not wait before starting to type. See https://www.cypress.io/blog/2019/01/22/when-can-the-test-click/
});
it('happy path for mobile/mouse users', () => {
cy.log(`Preparing for testing loading messages`);
const interception = interceptIndefinitely(
'https://maps.googleapis.com/maps/api/place/js/PlaceService.GetPlaceDetails',
);
cy.log('Typing a place name...');
cy.focused().realType(searchWords[0].source);
cy.log('...shows autocomplete suggesstions');
Expand All @@ -71,58 +82,66 @@ describe('Place search feature', () => {
cy.focused().realPress('Space').realType(searchWords[1].source);
cy.log('Selecting one of the autocomplete suggestions');
cy.findByRole('option', {name: placeName, timeout: 20000}).click();
cy.log('...Shows the place on the map');
cy.findByRole('button', {name: placeName}).should('be.visible');
cy.log('...Shows the place info');
cy.findByRole('heading', {name: placeName}).should('be.visible');
cy.findByText(placeAddress).should('be.visible');
cy.log(
'...Shows the working link to open Google Maps in a new tab for more detailed information',
);
cy.findByText(linkText.searchedPlace)
.should('have.attr', 'target', '_blank')
.should('have.attr', 'rel', 'noreferrer')
.then(link => {
cy.request(link.prop('href')).its('status').should('eq', 200);
});
// TODO #207: Make the following test pass
// cy.log('...Focuses the close button');
// cy.focused().should(
// 'have.attr',
// 'aria-label',
// buttonLabel.closePlaceDetail,
// );
cy.log('...initially shows a loading message');
cy.findByText(loadingMessage.search)
.should('be.visible')
.then(() => {
cy.log(`And then...`);
interception.sendResponse();

cy.log('Clicking the close button closes the place info');
cy.findByRole('button', {name: buttonLabel.closePlaceDetail}).click();
cy.findByRole('heading', {name: placeName}).should('not.exist');
cy.log('...Shows the place on the map');
cy.findByRole('button', {name: placeName}).should('be.visible');
cy.log('...Shows the place info');
cy.findByRole('heading', {name: placeName}).should('be.visible');
cy.findByText(placeAddress).should('be.visible');
cy.log(
'...Shows the working link to open Google Maps in a new tab for more detailed information',
);
cy.findByText(linkText.searchedPlace)
.should('have.attr', 'target', '_blank')
.should('have.attr', 'rel', 'noreferrer')
.then(link => {
cy.request(link.prop('href')).its('status').should('eq', 200);
});
// TODO #207: Make the following test pass
// cy.log('...Focuses the close button');
// cy.focused().should(
// 'have.attr',
// 'aria-label',
// buttonLabel.closePlaceDetail,
// );

cy.log('Clicking the place on the map...');
cy.findByRole('button', {name: placeName}).click();
cy.log('...reopens the place info');
cy.findByRole('heading', {name: placeName}).should('be.visible');
cy.log('...focuses the close button');
cy.focused().should(
'have.attr',
'aria-label',
buttonLabel.closePlaceDetail,
);
cy.log('Clicking the close button closes the place info');
cy.findByRole('button', {name: buttonLabel.closePlaceDetail}).click();
cy.findByRole('heading', {name: placeName}).should('not.exist');

cy.log('Pressing Esc key closes the place info');
cy.get('body').type('{esc}');
cy.findByRole('heading', {name: placeName}).should('not.exist');
cy.log('Clicking the place on the map...');
cy.findByRole('button', {name: placeName}).click();
cy.log('...reopens the place info');
cy.findByRole('heading', {name: placeName}).should('be.visible');
cy.log('...focuses the close button');
cy.focused().should(
'have.attr',
'aria-label',
buttonLabel.closePlaceDetail,
);

cy.log('Searching another place...');
cy.findByRole('button', {name: buttonLabel.search}).click();
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(100); // otherwise, Cypress will type 'bc', not 'abc'. This is a known issue. See https://www.cypress.io/blog/2019/01/22/when-can-the-test-click/
cy.focused().realType('fukuda art museum');
cy.findByRole('option', {
name: /fukuda art museum/i,
timeout: 20000,
}).click();
cy.log('...removes the place mark for the previous search');
cy.findByRole('button', {name: placeName}).should('not.exist');
cy.log('Pressing Esc key closes the place info');
cy.get('body').type('{esc}');
cy.findByRole('heading', {name: placeName}).should('not.exist');

cy.log('Searching another place...');
cy.findByRole('button', {name: buttonLabel.search}).click();
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(100); // otherwise, Cypress will type 'bc', not 'abc'. This is a known issue. See https://www.cypress.io/blog/2019/01/22/when-can-the-test-click/
cy.focused().realType('fukuda art museum');
cy.findByRole('option', {
name: /fukuda art museum/i,
timeout: 20000,
}).click();
cy.log('...removes the place mark for the previous search');
cy.findByRole('button', {name: placeName}).should('not.exist');
});
});
it('keeps displaying autocomplete suggestions when blurring the search box', () => {
cy.log('Setup: Type a place name');
Expand Down Expand Up @@ -213,3 +232,50 @@ describe('Place search feature', () => {
}).should('not.exist');
});
});
describe('Sad path', () => {
beforeEach(() => {
cy.log('Loading app');
cy.auth();
cy.visit('/');
cy.waitForMapToLoad();
cy.log('Opening the search box');
cy.findByRole('button', {name: buttonLabel.search}).click();
cy.findByRole('combobox').should('be.visible'); // Wait for search box module to be loaded; Cypress may not wait before starting to type. See https://www.cypress.io/blog/2019/01/22/when-can-the-test-click/
});
it('Shows error message when Place Detail API fails', () => {
cy.log(`Mocking API failure`);
cy.intercept(
'https://maps.googleapis.com/maps/api/place/js/PlaceService.GetPlaceDetails*',
request => {
console.log(`cy.intercept is running`);
const searchParams = new URLSearchParams(request.url);
const callbackParam = searchParams.get('callback');
request.reply(
`${callbackParam} && ${callbackParam}(${JSON.stringify({
status: 'UNKNOWN_ERROR',
})})`,
);
},
).as('PlaceDetailsAPI');
cy.log('Typing a place name and...');
cy.focused()
.realType(searchWords[0].source)
.realPress('Space')
.realType(searchWords[1].source);
cy.log('Selecting one of the autocomplete suggestions');
cy.findByRole('option', {name: placeName, timeout: 20000}).click();
cy.log('...shows an error message');
cy.findByRole('alertdialog', {
name: errorMessage.placeDetails.title,
}).should('be.visible');
cy.log('...autofocuses the Got It button');
cy.focused().should('have.attr', 'type', 'button');
cy.focused().should('have.text', buttonLabel.handleError);
cy.log('...traps focus between link text and the Got It button');
cy.realPress('Tab');
cy.focused().should('have.attr', 'target', '_blank');
cy.realPress('Tab');
cy.focused().should('have.attr', 'type', 'button');
cy.focused().should('have.text', buttonLabel.handleError);
});
});
5 changes: 4 additions & 1 deletion cypress/e2e/to-be-fixed.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ describe(`menu.cy.js`, () => {
it.skip('closes menu after pressing ESC key', () => {
cy.log(`Clicking menu button and ...`);
cy.findByRole('button', {name: buttonLabel.menu}).click();
cy.log(`Pressing ESC key also closes the menu`);
cy.log(`Pressing ESC key...`);
cy.get('body').type('{esc}');
cy.log('...Hides the search box');
cy.findByRole('dialog', {name: menuLabel}).should('not.exist');
cy.log('...Focuses the search icon button');
cy.focused().should('have.attr', 'aria-label', buttonLabel.menu);
});
});
describe(`search.cy.js`, () => {
Expand Down
Loading

1 comment on commit 43c8314

@vercel
Copy link

@vercel vercel bot commented on 43c8314 Apr 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.