diff --git a/.eslintrc b/.eslintrc index 5af1e125..86ef0c08 100644 --- a/.eslintrc +++ b/.eslintrc @@ -8,8 +8,13 @@ "FileReader": true, "localStorage": true }, - "extends": ["airbnb", "prettier"], - "plugins": ["prettier"], + "extends": [ + "airbnb", + "plugin:jest/recommended", + "plugin:jest/style", + "prettier" + ], + "plugins": ["jest", "prettier"], "rules": { "import/no-extraneous-dependencies": ["error", { "devDependencies": true }], "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }], diff --git a/__mocks__/__tests__/gatsby-plugin-firebase.test.js b/__mocks__/__tests__/gatsby-plugin-firebase.test.js index d75dfcdc..9094c01a 100644 --- a/__mocks__/__tests__/gatsby-plugin-firebase.test.js +++ b/__mocks__/__tests__/gatsby-plugin-firebase.test.js @@ -1,4 +1,7 @@ -import FirebaseStub, { AuthConstants } from '../gatsby-plugin-firebase'; +import FirebaseStub, { + AuthConstants, + DatabaseConstants, +} from '../gatsby-plugin-firebase'; describe('FirebaseStub', () => { const { resumesPath } = FirebaseStub.database(); @@ -49,14 +52,14 @@ describe('FirebaseStub', () => { const observer = () => {}; const unsubscribe = FirebaseStub.auth().onAuthStateChanged(observer); expect(unsubscribe).toBeTruthy(); - expect(FirebaseStub.auth().onAuthStateChangedObservers.length).toEqual(1); + expect(FirebaseStub.auth().onAuthStateChangedObservers).toHaveLength(1); expect(FirebaseStub.auth().onAuthStateChangedObservers[0]).toEqual( observer, ); unsubscribe(); - expect(FirebaseStub.auth().onAuthStateChangedObservers.length).toEqual(0); + expect(FirebaseStub.auth().onAuthStateChangedObservers).toHaveLength(0); }); }); @@ -110,30 +113,24 @@ describe('FirebaseStub', () => { const resumesDataSnapshot = await resumesRef.once('value'); const resumes = resumesDataSnapshot.val(); expect(resumes).toBeTruthy(); - expect(Object.keys(resumes).length).toEqual(3); - const demoStateResume1 = - resumes[FirebaseStub.database().demoStateResume1Id]; + expect(Object.keys(resumes)).toHaveLength(3); + const demoStateResume1 = resumes[DatabaseConstants.demoStateResume1Id]; expect(demoStateResume1).toBeTruthy(); - expect(demoStateResume1.id).toEqual( - FirebaseStub.database().demoStateResume1Id, - ); + expect(demoStateResume1.id).toEqual(DatabaseConstants.demoStateResume1Id); expect(demoStateResume1.user).toEqual( FirebaseStub.database().anonymousUser1.uid, ); - const demoStateResume2 = - resumes[FirebaseStub.database().demoStateResume2Id]; + const demoStateResume2 = resumes[DatabaseConstants.demoStateResume2Id]; expect(demoStateResume2).toBeTruthy(); - expect(demoStateResume2.id).toEqual( - FirebaseStub.database().demoStateResume2Id, - ); + expect(demoStateResume2.id).toEqual(DatabaseConstants.demoStateResume2Id); expect(demoStateResume2.user).toEqual( FirebaseStub.database().anonymousUser2.uid, ); const initialStateResume = - resumes[FirebaseStub.database().initialStateResumeId]; + resumes[DatabaseConstants.initialStateResumeId]; expect(initialStateResume).toBeTruthy(); expect(initialStateResume.id).toEqual( - FirebaseStub.database().initialStateResumeId, + DatabaseConstants.initialStateResumeId, ); expect(initialStateResume.user).toEqual( FirebaseStub.database().anonymousUser1.uid, @@ -143,7 +140,7 @@ describe('FirebaseStub', () => { const usersDataSnapshot = await usersRef.once('value'); const users = usersDataSnapshot.val(); expect(users).toBeTruthy(); - expect(Object.keys(users).length).toEqual(2); + expect(Object.keys(users)).toHaveLength(2); const anonymousUser1 = users[FirebaseStub.database().anonymousUser1.uid]; expect(anonymousUser1).toBeTruthy(); expect(anonymousUser1).toEqual(FirebaseStub.database().anonymousUser1); @@ -157,12 +154,12 @@ describe('FirebaseStub', () => { const resume = ( await FirebaseStub.database() - .ref(`${resumesPath}/${FirebaseStub.database().demoStateResume1Id}`) + .ref(`${resumesPath}/${DatabaseConstants.demoStateResume1Id}`) .once('value') ).val(); expect(resume).toBeTruthy(); - expect(resume.id).toEqual(FirebaseStub.database().demoStateResume1Id); + expect(resume.id).toEqual(DatabaseConstants.demoStateResume1Id); }); it('retrieves null if resume does not exist', async () => { @@ -243,7 +240,7 @@ describe('FirebaseStub', () => { snapshotValue = snapshot.val(); }); - expect(Object.keys(snapshotValue).length).toEqual(2); + expect(Object.keys(snapshotValue)).toHaveLength(2); Object.values(snapshotValue).forEach((resume) => expect(resume.user).toEqual(FirebaseStub.database().anonymousUser1.uid), ); diff --git a/__mocks__/gatsby-plugin-firebase.js b/__mocks__/gatsby-plugin-firebase.js index ed51b926..8494e485 100644 --- a/__mocks__/gatsby-plugin-firebase.js +++ b/__mocks__/gatsby-plugin-firebase.js @@ -2,7 +2,10 @@ import path from 'path'; import fs from 'fs'; import { v4 as uuidv4 } from 'uuid'; -import { AuthConstants } from './gatsby-plugin-firebase/constants'; +import { + AuthConstants, + DatabaseConstants, +} from './gatsby-plugin-firebase/constants'; class Auth { static #instance = undefined; @@ -57,9 +60,6 @@ class Database { #references = {}; #anonymousUser1 = undefined; #anonymousUser2 = undefined; - #demoStateResume1Id = 'demo_1'; - #demoStateResume2Id = 'demo_2'; - #initialStateResumeId = 'initst'; constructor() { if (Database.#instance) { @@ -99,18 +99,6 @@ class Database { return this.#anonymousUser2; } - get demoStateResume1Id() { - return this.#demoStateResume1Id; - } - - get demoStateResume2Id() { - return this.#demoStateResume2Id; - } - - get initialStateResumeId() { - return this.#initialStateResumeId; - } - get uuid() { return this.#uuid; } @@ -131,11 +119,11 @@ class Database { date.setMonth(date.getMonth() - 2); demoStateResume1.createdAt = date.valueOf(); demoStateResume1.user = this.anonymousUser1.uid; - resumes[this.demoStateResume1Id] = demoStateResume1; + resumes[DatabaseConstants.demoStateResume1Id] = demoStateResume1; const demoStateResume2 = JSON.parse(JSON.stringify(demoStateResume1)); demoStateResume2.user = this.anonymousUser2.uid; - resumes[this.demoStateResume2Id] = demoStateResume2; + resumes[DatabaseConstants.demoStateResume2Id] = demoStateResume2; const initialStateResume = Database.readFile( '../src/data/initialState.json', @@ -143,7 +131,7 @@ class Database { initialStateResume.updatedAt = date.valueOf(); initialStateResume.createdAt = date.valueOf(); initialStateResume.user = this.anonymousUser1.uid; - resumes[this.initialStateResumeId] = initialStateResume; + resumes[DatabaseConstants.initialStateResumeId] = initialStateResume; for (var key in resumes) { const resume = resumes[key]; @@ -372,4 +360,4 @@ Object.defineProperty(FirebaseStub.database.ServerValue, 'TIMESTAMP', { }); export default FirebaseStub; -export { AuthConstants }; +export { AuthConstants, DatabaseConstants }; diff --git a/__mocks__/gatsby-plugin-firebase/constants.js b/__mocks__/gatsby-plugin-firebase/constants.js index 0fef2af1..53e34eaa 100644 --- a/__mocks__/gatsby-plugin-firebase/constants.js +++ b/__mocks__/gatsby-plugin-firebase/constants.js @@ -1 +1,4 @@ -export { Auth as AuthConstants } from './constants/auth'; +import AuthConstants from './constants/auth'; +import DatabaseConstants from './constants/database'; + +export { AuthConstants, DatabaseConstants }; diff --git a/__mocks__/gatsby-plugin-firebase/constants/auth.js b/__mocks__/gatsby-plugin-firebase/constants/auth.js index 33ea4970..9280bfd9 100644 --- a/__mocks__/gatsby-plugin-firebase/constants/auth.js +++ b/__mocks__/gatsby-plugin-firebase/constants/auth.js @@ -1,19 +1,27 @@ -class Auth { - static anonymousUser1 = { - displayName: 'Anonymous User 1', - email: 'anonymous1@noemail.com', - isAnonymous: true, - name: 'Anonymous 1', - uid: 'anonym123', - }; +const anonymousUser1 = { + displayName: 'Anonymous User 1', + email: 'anonymous1@noemail.com', + isAnonymous: true, + name: 'Anonymous 1', + uid: 'anonym123', +}; - static anonymousUser2 = { - displayName: 'Anonymous User 2', - email: 'anonymous2@noemail.com', - isAnonymous: true, - name: 'Anonymous 2', - uid: 'anonym456', - }; +const anonymousUser2 = { + displayName: 'Anonymous User 2', + email: 'anonymous2@noemail.com', + isAnonymous: true, + name: 'Anonymous 2', + uid: 'anonym456', +}; + +class Auth { + static get anonymousUser1() { + return anonymousUser1; + } + + static get anonymousUser2() { + return anonymousUser2; + } } -export { Auth }; +export default Auth; diff --git a/__mocks__/gatsby-plugin-firebase/constants/database.js b/__mocks__/gatsby-plugin-firebase/constants/database.js new file mode 100644 index 00000000..edcb65ec --- /dev/null +++ b/__mocks__/gatsby-plugin-firebase/constants/database.js @@ -0,0 +1,19 @@ +const demoStateResume1Id = 'demo_1'; +const demoStateResume2Id = 'demo_2'; +const initialStateResumeId = 'initst'; + +class Database { + static get demoStateResume1Id() { + return demoStateResume1Id; + } + + static get demoStateResume2Id() { + return demoStateResume2Id; + } + + static get initialStateResumeId() { + return initialStateResumeId; + } +} + +export default Database; diff --git a/package-lock.json b/package-lock.json index 501ed4b9..7628193d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4291,6 +4291,22 @@ "eslint-visitor-keys": "^1.1.0" } }, + "@typescript-eslint/scope-manager": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.12.0.tgz", + "integrity": "sha512-QVf9oCSVLte/8jvOsxmgBdOaoe2J0wtEmBr13Yz0rkBNkl5D8bfnf6G4Vhox9qqMIoG7QQoVwd2eG9DM/ge4Qg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.12.0", + "@typescript-eslint/visitor-keys": "4.12.0" + } + }, + "@typescript-eslint/types": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.12.0.tgz", + "integrity": "sha512-N2RhGeheVLGtyy+CxRmxdsniB7sMSCfsnbh8K/+RUIXYYq3Ub5+sukRCjVE80QerrUBvuEvs4fDhz5AW/pcL6g==", + "dev": true + }, "@typescript-eslint/typescript-estree": { "version": "2.34.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz", @@ -4315,6 +4331,24 @@ } } }, + "@typescript-eslint/visitor-keys": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.12.0.tgz", + "integrity": "sha512-hVpsLARbDh4B9TKYz5cLbcdMIOAoBYgFPCSP9FFS/liSF+b33gVNq8JHY3QGhHNVz85hObvL7BEYLlgx553WCw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.12.0", + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "dev": true + } + } + }, "@webassemblyjs/ast": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", @@ -10110,6 +10144,70 @@ } } }, + "eslint-plugin-jest": { + "version": "24.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-24.1.3.tgz", + "integrity": "sha512-dNGGjzuEzCE3d5EPZQ/QGtmlMotqnYWD/QpCZ1UuZlrMAdhG5rldh0N0haCvhGnUkSeuORS5VNROwF9Hrgn3Lg==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "^4.0.1" + }, + "dependencies": { + "@typescript-eslint/experimental-utils": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.12.0.tgz", + "integrity": "sha512-MpXZXUAvHt99c9ScXijx7i061o5HEjXltO+sbYfZAAHxv3XankQkPaNi5myy0Yh0Tyea3Hdq1pi7Vsh0GJb0fA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/scope-manager": "4.12.0", + "@typescript-eslint/types": "4.12.0", + "@typescript-eslint/typescript-estree": "4.12.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + } + }, + "@typescript-eslint/typescript-estree": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.12.0.tgz", + "integrity": "sha512-gZkFcmmp/CnzqD2RKMich2/FjBTsYopjiwJCroxqHZIY11IIoN0l5lKqcgoAPKHt33H2mAkSfvzj8i44Jm7F4w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.12.0", + "@typescript-eslint/visitor-keys": "4.12.0", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "globby": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz", + "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, "eslint-plugin-jsx-a11y": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz", diff --git a/package.json b/package.json index b72efbf1..47e10ac1 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "eslint-config-airbnb": "^18.2.1", "eslint-config-prettier": "^7.1.0", "eslint-loader": "^4.0.2", + "eslint-plugin-jest": "^24.1.3", "eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-prettier": "^3.3.0", "eslint-plugin-react": "^7.22.0", diff --git a/src/pages/app/__tests__/builder.test.js b/src/pages/app/__tests__/builder.test.js index 3ce73d51..45f0f619 100644 --- a/src/pages/app/__tests__/builder.test.js +++ b/src/pages/app/__tests__/builder.test.js @@ -7,7 +7,7 @@ import { waitFor, } from '@testing-library/react'; -import FirebaseStub from 'gatsby-plugin-firebase'; +import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase'; import { SettingsProvider } from '../../../contexts/SettingsContext'; import { ModalProvider } from '../../../contexts/ModalContext'; @@ -25,14 +25,13 @@ beforeEach(() => { }); describe('Builder', () => { - const resumesPath = FirebaseStub.database().resumesPath; + const { resumesPath } = FirebaseStub.database(); let resumeId = null; let resume = null; let mockUpdateFunction = null; - let container = null; beforeEach(async () => { - resumeId = FirebaseStub.database().demoStateResume1Id; + resumeId = DatabaseConstants.demoStateResume1Id; resume = ( await FirebaseStub.database() .ref(`${resumesPath}/${resumeId}`) @@ -43,7 +42,7 @@ describe('Builder', () => { 'update', ); - container = render( + render( diff --git a/src/pages/app/__tests__/dashboard.test.js b/src/pages/app/__tests__/dashboard.test.js index 43018617..fe4c5490 100644 --- a/src/pages/app/__tests__/dashboard.test.js +++ b/src/pages/app/__tests__/dashboard.test.js @@ -17,10 +17,9 @@ beforeEach(() => { }); describe('Dashboard', () => { - const resumesPath = FirebaseStub.database().resumesPath; + const { resumesPath } = FirebaseStub.database(); let resumes = null; - let user = FirebaseStub.database().anonymousUser1; - let container = null; + const user = FirebaseStub.database().anonymousUser1; beforeEach(async () => { resumes = ( @@ -30,10 +29,8 @@ describe('Dashboard', () => { .equalTo(user.uid) .once('value') ).val(); - expect(resumes).toBeTruthy(); - expect(Object.keys(resumes).length).not.toEqual(0); - container = render( + render( @@ -60,7 +57,7 @@ describe('Dashboard', () => { }); it('preview of user resumes', async () => { - expect(Object.keys(resumes).length).toEqual(2); + expect(Object.keys(resumes)).toHaveLength(2); expect(Object.values(resumes)[0].user).toEqual(user.uid); expect( diff --git a/src/templates/__tests__/Castform.test.js b/src/templates/__tests__/Castform.test.js index 57d76764..53327b44 100644 --- a/src/templates/__tests__/Castform.test.js +++ b/src/templates/__tests__/Castform.test.js @@ -1,6 +1,6 @@ import React from 'react'; import { render } from '@testing-library/react'; -import FirebaseStub from 'gatsby-plugin-firebase'; +import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase'; import '../../i18n/index'; import Castform from '../Castform'; @@ -10,8 +10,8 @@ describe('Castform', () => { beforeEach(async () => { FirebaseStub.database().initializeData(); - const resumesPath = FirebaseStub.database().resumesPath; - const resumeId = FirebaseStub.database().initialStateResumeId; + const { resumesPath } = FirebaseStub.database(); + const resumeId = DatabaseConstants.initialStateResumeId; resume = ( await FirebaseStub.database() .ref(`${resumesPath}/${resumeId}`) @@ -32,7 +32,7 @@ describe('Castform', () => { it('is not shown if not provided', () => { const { queryByText } = render(); - expect(queryByText(birthDateLabelMatcher)).toBe(null); + expect(queryByText(birthDateLabelMatcher)).toBeNull(); }); it('is shown if provided', () => {