From 781d8998a729242c78af79a16a10c4acc83d0537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Vannicatte?= Date: Fri, 12 Aug 2022 16:25:41 +0200 Subject: [PATCH 1/3] fix(navigator): check for experimental `userAgentData` first --- .circleci/config.yml | 7 +++-- .eslintrc.js | 1 + cypress/integration/search/actions.spec.ts | 30 +++++++++++++++++++ package.json | 6 ++-- .../docsearch-react/src/DocSearchButton.tsx | 6 +++- .../src/__tests__/api.test.tsx | 26 +++++++++------- 6 files changed, 59 insertions(+), 17 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index aed77c93e..17390d89f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -159,8 +159,11 @@ jobs: - save_cache: *save_yarn_cache - run: *restore_dist_folders - run: - name: Cypress test Actions - command: yarn run cy:run + name: Cypress test on Chrome + command: yarn run cy:run:chrome + - run: + name: Cypress test on Firefox + command: yarn run cy:run:firefox workflows: version: 2 diff --git a/.eslintrc.js b/.eslintrc.js index 67b0a180b..38ffe4a14 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -68,6 +68,7 @@ module.exports = { }, rules: { 'jest/expect-expect': 0, + 'jest/valid-expect': 0, 'spaced-comment': 0, '@typescript-eslint/triple-slash-reference': 0, }, diff --git a/cypress/integration/search/actions.spec.ts b/cypress/integration/search/actions.spec.ts index 162e490d1..ac1d823ed 100644 --- a/cypress/integration/search/actions.spec.ts +++ b/cypress/integration/search/actions.spec.ts @@ -138,3 +138,33 @@ describe('Recent and Favorites', () => { cy.contains('No recent searches').should('be.visible'); }); }); + +describe('Navigator', () => { + it( + 'Use correct navigator to detect Apple device on chrome', + { browser: 'chrome' }, + () => { + expect((navigator as any).userAgentData).not.be.undefined; + expect(navigator.platform).not.to.be.undefined; + + cy.visit(Cypress.config().baseUrl!); + + cy.get('body').type('{meta}k'); + cy.modalIsVisibleAndFocused(); + } + ); + + it( + 'Use correct navigator to detect Apple device on non chrome browser', + { browser: '!chrome' }, + () => { + expect((navigator as any).userAgentData).to.be.undefined; + expect(navigator.platform).not.to.be.undefined; + + cy.visit(Cypress.config().baseUrl!); + + cy.get('body').type('{meta}k'); + cy.modalIsVisibleAndFocused(); + } + ); +}); diff --git a/package.json b/package.json index c8937d310..58255ee96 100644 --- a/package.json +++ b/package.json @@ -18,10 +18,8 @@ "build": "lerna run build --scope @docsearch/*", "cy:clean": "rm -rf cypress/screenshots", "cy:info": "cypress info", - "cy:run:chrome": "yarn run cy:run --browser chrome", - "cy:run:edge": "yarn run cy:run --browser edge", - "cy:run:firefox": "yarn run cy:run --browser firefox", - "cy:run": "start-server-and-test 'yarn website:test' http://localhost:3000 'cypress run --spec 'cypress/integration/**/*' --headless'", + "cy:run:chrome": "start-server-and-test 'yarn website:test' http://localhost:3000 'cypress run --browser chrome --spec 'cypress/integration/**/*' --headless'", + "cy:run:firefox": "start-server-and-test 'yarn website:test' http://localhost:3000 'cypress run --browser firefox --spec 'cypress/integration/**/*' --headless'", "cy:verify": "cypress verify", "lint:css": "stylelint **/src/**/*.css", "lint": "eslint --ext .js,.ts,.tsx .", diff --git a/packages/docsearch-react/src/DocSearchButton.tsx b/packages/docsearch-react/src/DocSearchButton.tsx index 57d62347f..645c32f7f 100644 --- a/packages/docsearch-react/src/DocSearchButton.tsx +++ b/packages/docsearch-react/src/DocSearchButton.tsx @@ -16,7 +16,11 @@ const ACTION_KEY_DEFAULT = 'Ctrl' as const; const ACTION_KEY_APPLE = '⌘' as const; function isAppleDevice() { - return /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform); + return /(Mac|iPhone|iPod|iPad)/i.test( + // `userAgentData` is not supported everywhere and still experimental + // so types are not provided yet. + (navigator as any)?.userAgentData?.platform || navigator.platform + ); } export const DocSearchButton = React.forwardRef< diff --git a/packages/docsearch-react/src/__tests__/api.test.tsx b/packages/docsearch-react/src/__tests__/api.test.tsx index 656ab5fc9..419f52604 100644 --- a/packages/docsearch-react/src/__tests__/api.test.tsx +++ b/packages/docsearch-react/src/__tests__/api.test.tsx @@ -34,7 +34,7 @@ function noResultSearch(_queries: any, _requestOptions?: any): Promise { } describe('api', () => { - let container: HTMLDivElement; + let container: HTMLDivElement | null; const docSearchSelector = '.DocSearch'; @@ -44,8 +44,10 @@ describe('api', () => { }); afterEach(() => { - document.body.removeChild(container); - container = null; + if (container) { + document.body.removeChild(container); + container = null; + } }); it('renders with minimal parameters', () => { @@ -66,12 +68,13 @@ describe('api', () => { }} /> ); + // We can silence the potentially undefined here because we assert that they are not expect(document.querySelector(docSearchSelector)).toBeInTheDocument(); expect( - document.querySelector('.DocSearch-Button-Placeholder').innerHTML + document.querySelector('.DocSearch-Button-Placeholder')!.innerHTML ).toBe('Recherche'); expect( - document.querySelector('.DocSearch-Button').getAttribute('aria-label') + document.querySelector('.DocSearch-Button')!.getAttribute('aria-label') ).toBe('Recherche'); }); @@ -166,17 +169,18 @@ describe('api', () => { fireEvent.click(await screen.findByText('Search')); }); - expect(document.querySelector('.DocSearch-Cancel').innerHTML).toBe( + // We can silence the potentially undefined here because we assert that they are not + expect(document.querySelector('.DocSearch-Cancel')!.innerHTML).toBe( 'Annuler' ); expect( - document.querySelector('.DocSearch-Cancel').getAttribute('aria-label') + document.querySelector('.DocSearch-Cancel')!.getAttribute('aria-label') ).toBe('Annuler'); expect( - document.querySelector('.DocSearch-Reset').getAttribute('title') + document.querySelector('.DocSearch-Reset')!.getAttribute('title') ).toBe('Effacer'); expect( - document.querySelector('.DocSearch-Reset').getAttribute('aria-label') + document.querySelector('.DocSearch-Reset')!.getAttribute('aria-label') ).toBe('Effacer'); }); @@ -290,9 +294,11 @@ describe('api', () => { }); expect(screen.getByText(/No results for/)).toBeInTheDocument(); + + // We can silence the potentially undefined here because we assert that they are not const link = document.querySelector('.DocSearch-Help a'); expect(link).toBeInTheDocument(); - expect(link.getAttribute('href')).toBe( + expect(link!.getAttribute('href')).toBe( 'https://github.com/algolia/docsearch/issues/new?title=q' ); }); From aa51a59220b844d9f98079f8c8a0749b1f43a5e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Vannicatte?= Date: Fri, 9 Sep 2022 14:17:41 +0200 Subject: [PATCH 2/3] bundlesize --- bundlesize.config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundlesize.config.json b/bundlesize.config.json index b8e8f9d75..c3ac3fa35 100644 --- a/bundlesize.config.json +++ b/bundlesize.config.json @@ -10,7 +10,7 @@ }, { "path": "packages/docsearch-js/dist/umd/index.js", - "maxSize": "28.20 kB" + "maxSize": "28.25 kB" } ] } From a90cdb86478a390c8d6f5473b49cc6c559ee9fb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Vannicatte?= Date: Tue, 8 Nov 2022 08:58:04 +0100 Subject: [PATCH 3/3] remove ts comment --- packages/docsearch-react/src/__tests__/api.test.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/docsearch-react/src/__tests__/api.test.tsx b/packages/docsearch-react/src/__tests__/api.test.tsx index 419f52604..53b85bfc1 100644 --- a/packages/docsearch-react/src/__tests__/api.test.tsx +++ b/packages/docsearch-react/src/__tests__/api.test.tsx @@ -68,7 +68,6 @@ describe('api', () => { }} /> ); - // We can silence the potentially undefined here because we assert that they are not expect(document.querySelector(docSearchSelector)).toBeInTheDocument(); expect( document.querySelector('.DocSearch-Button-Placeholder')!.innerHTML @@ -169,7 +168,6 @@ describe('api', () => { fireEvent.click(await screen.findByText('Search')); }); - // We can silence the potentially undefined here because we assert that they are not expect(document.querySelector('.DocSearch-Cancel')!.innerHTML).toBe( 'Annuler' ); @@ -295,7 +293,6 @@ describe('api', () => { expect(screen.getByText(/No results for/)).toBeInTheDocument(); - // We can silence the potentially undefined here because we assert that they are not const link = document.querySelector('.DocSearch-Help a'); expect(link).toBeInTheDocument(); expect(link!.getAttribute('href')).toBe(