mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-07-13 06:24:54 +10:00
Merge pull request #443 from gianantoniopini/develop
Addition of some unit tests to the Dashboard page
This commit is contained in:
@@ -1,552 +0,0 @@
|
||||
import { waitFor } from '@testing-library/react';
|
||||
import FirebaseStub, {
|
||||
AuthConstants,
|
||||
DatabaseConstants,
|
||||
} from '../gatsby-plugin-firebase';
|
||||
|
||||
describe('FirebaseStub', () => {
|
||||
describe('auth', () => {
|
||||
it('reuses existing Auth instance', () => {
|
||||
const auth1 = FirebaseStub.auth();
|
||||
const auth2 = FirebaseStub.auth();
|
||||
|
||||
expect(auth1.uuid).toBeTruthy();
|
||||
expect(auth2.uuid).toBeTruthy();
|
||||
expect(auth1.uuid).toEqual(auth2.uuid);
|
||||
});
|
||||
|
||||
it('returns anonymous user 1 when signing in anonymously', async () => {
|
||||
const user = await FirebaseStub.auth().signInAnonymously();
|
||||
|
||||
expect(user).toBeTruthy();
|
||||
expect(user).toEqual(AuthConstants.anonymousUser1);
|
||||
});
|
||||
|
||||
it('calls onAuthStateChanged observer with anonymous user 1 when signing in anonymously', async () => {
|
||||
let user = null;
|
||||
let error = null;
|
||||
FirebaseStub.auth().onAuthStateChanged(
|
||||
(_user) => {
|
||||
user = _user;
|
||||
},
|
||||
(_error) => {
|
||||
error = _error;
|
||||
},
|
||||
);
|
||||
|
||||
await FirebaseStub.auth().signInAnonymously();
|
||||
|
||||
expect(user).toBeTruthy();
|
||||
expect(user).toEqual(AuthConstants.anonymousUser1);
|
||||
expect(error).toBeNull();
|
||||
});
|
||||
|
||||
it('onAuthStateChanged unsubscribe removes observer', () => {
|
||||
const observer = () => {};
|
||||
const unsubscribe = FirebaseStub.auth().onAuthStateChanged(observer);
|
||||
expect(unsubscribe).toBeTruthy();
|
||||
expect(
|
||||
FirebaseStub.auth().onAuthStateChangedObservers.indexOf(observer),
|
||||
).toBeGreaterThanOrEqual(0);
|
||||
|
||||
unsubscribe();
|
||||
|
||||
expect(
|
||||
FirebaseStub.auth().onAuthStateChangedObservers.indexOf(observer),
|
||||
).not.toBeGreaterThanOrEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('database', () => {
|
||||
beforeEach(() => {
|
||||
FirebaseStub.database().initializeData();
|
||||
});
|
||||
|
||||
it('reuses existing Database instance', () => {
|
||||
const database1 = FirebaseStub.database();
|
||||
const database2 = FirebaseStub.database();
|
||||
|
||||
expect(database1.uuid).toBeTruthy();
|
||||
expect(database2.uuid).toBeTruthy();
|
||||
expect(database1.uuid).toEqual(database2.uuid);
|
||||
});
|
||||
|
||||
describe('ref function', () => {
|
||||
it('reuses existing Reference instance', () => {
|
||||
const ref1 = FirebaseStub.database().ref(
|
||||
`${DatabaseConstants.resumesPath}/123`,
|
||||
);
|
||||
const ref2 = FirebaseStub.database().ref(
|
||||
`${DatabaseConstants.resumesPath}/123`,
|
||||
);
|
||||
|
||||
expect(ref1).toBeTruthy();
|
||||
expect(ref2).toBeTruthy();
|
||||
expect(ref1).toEqual(ref2);
|
||||
});
|
||||
|
||||
it('leading slash in reference path is ignored', () => {
|
||||
const path = `${DatabaseConstants.resumesPath}/123`;
|
||||
|
||||
const ref1 = FirebaseStub.database().ref(path);
|
||||
expect(ref1).toBeTruthy();
|
||||
expect(ref1.path).toEqual(path);
|
||||
|
||||
const ref2 = FirebaseStub.database().ref(`/${path}`);
|
||||
expect(ref2).toBeTruthy();
|
||||
expect(ref2).toEqual(ref1);
|
||||
});
|
||||
});
|
||||
|
||||
it('ServerValue.TIMESTAMP returns current time in milliseconds', () => {
|
||||
const now = new Date().getTime();
|
||||
const timestamp = FirebaseStub.database.ServerValue.TIMESTAMP;
|
||||
|
||||
expect(timestamp).toBeTruthy();
|
||||
expect(timestamp).toBeGreaterThanOrEqual(now);
|
||||
});
|
||||
|
||||
it('initializing data sets up resumes and users', async () => {
|
||||
const resumesRef = FirebaseStub.database().ref(
|
||||
DatabaseConstants.resumesPath,
|
||||
);
|
||||
const resumesDataSnapshot = await resumesRef.once('value');
|
||||
const resumes = resumesDataSnapshot.val();
|
||||
expect(resumes).toBeTruthy();
|
||||
expect(Object.keys(resumes)).toHaveLength(3);
|
||||
const demoStateResume1 = resumes[DatabaseConstants.demoStateResume1Id];
|
||||
expect(demoStateResume1).toBeTruthy();
|
||||
expect(demoStateResume1.id).toEqual(DatabaseConstants.demoStateResume1Id);
|
||||
expect(demoStateResume1.user).toEqual(DatabaseConstants.user1.uid);
|
||||
const demoStateResume2 = resumes[DatabaseConstants.demoStateResume2Id];
|
||||
expect(demoStateResume2).toBeTruthy();
|
||||
expect(demoStateResume2.id).toEqual(DatabaseConstants.demoStateResume2Id);
|
||||
expect(demoStateResume2.user).toEqual(DatabaseConstants.user2.uid);
|
||||
const initialStateResume =
|
||||
resumes[DatabaseConstants.initialStateResumeId];
|
||||
expect(initialStateResume).toBeTruthy();
|
||||
expect(initialStateResume.id).toEqual(
|
||||
DatabaseConstants.initialStateResumeId,
|
||||
);
|
||||
expect(initialStateResume.user).toEqual(DatabaseConstants.user1.uid);
|
||||
|
||||
const usersRef = FirebaseStub.database().ref(DatabaseConstants.usersPath);
|
||||
const usersDataSnapshot = await usersRef.once('value');
|
||||
const users = usersDataSnapshot.val();
|
||||
expect(users).toBeTruthy();
|
||||
expect(Object.keys(users)).toHaveLength(2);
|
||||
const anonymousUser1 = users[DatabaseConstants.user1.uid];
|
||||
expect(anonymousUser1).toBeTruthy();
|
||||
expect(anonymousUser1).toEqual(DatabaseConstants.user1);
|
||||
const anonymousUser2 = users[DatabaseConstants.user2.uid];
|
||||
expect(anonymousUser2).toBeTruthy();
|
||||
expect(anonymousUser2).toEqual(DatabaseConstants.user2);
|
||||
});
|
||||
|
||||
it('retrieves resume if it exists', async () => {
|
||||
const resume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(
|
||||
`${DatabaseConstants.resumesPath}/${DatabaseConstants.demoStateResume1Id}`,
|
||||
)
|
||||
.once('value')
|
||||
).val();
|
||||
|
||||
expect(resume).toBeTruthy();
|
||||
expect(resume.id).toEqual(DatabaseConstants.demoStateResume1Id);
|
||||
});
|
||||
|
||||
it('retrieves null if resume does not exist', async () => {
|
||||
const resumeId = 'invalidResumeId';
|
||||
|
||||
const resume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.once('value')
|
||||
).val();
|
||||
|
||||
expect(resume).toBeNull();
|
||||
});
|
||||
|
||||
it('retrieves user if it exists', async () => {
|
||||
const user = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.usersPath}/${DatabaseConstants.user1.uid}`)
|
||||
.once('value')
|
||||
).val();
|
||||
|
||||
expect(user).toBeTruthy();
|
||||
expect(user).toEqual(DatabaseConstants.user1);
|
||||
});
|
||||
|
||||
it('retrieves null if user does not exist', async () => {
|
||||
const userId = 'invalidUserId';
|
||||
|
||||
const user = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.usersPath}/${userId}`)
|
||||
.once('value')
|
||||
).val();
|
||||
|
||||
expect(user).toBeNull();
|
||||
});
|
||||
|
||||
describe('on function', () => {
|
||||
describe('value event', () => {
|
||||
it('triggers event with true if on the connected reference path', async () => {
|
||||
let snapshotValue = null;
|
||||
|
||||
FirebaseStub.database()
|
||||
.ref(DatabaseConstants.connectedPath)
|
||||
.on('value', (snapshot) => {
|
||||
snapshotValue = snapshot.val();
|
||||
});
|
||||
|
||||
await waitFor(() =>
|
||||
snapshotValue ? Promise.resolve(true) : Promise.reject(),
|
||||
);
|
||||
|
||||
expect(snapshotValue).not.toBeNull();
|
||||
expect(snapshotValue).toBe(true);
|
||||
});
|
||||
|
||||
it('triggers event with resumes if on the resumes reference path', async () => {
|
||||
const resumesDataSnapshot = await FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.once('value');
|
||||
const resumes = resumesDataSnapshot.val();
|
||||
let snapshotValue = null;
|
||||
|
||||
FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.on('value', (snapshot) => {
|
||||
snapshotValue = snapshot.val();
|
||||
});
|
||||
|
||||
await waitFor(() =>
|
||||
snapshotValue ? Promise.resolve(true) : Promise.reject(),
|
||||
);
|
||||
|
||||
expect(snapshotValue).not.toBeNull();
|
||||
expect(snapshotValue).toEqual(resumes);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('can filter resumes by user', async () => {
|
||||
let snapshotValue = null;
|
||||
|
||||
FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo(DatabaseConstants.user1.uid)
|
||||
.on('value', (snapshot) => {
|
||||
snapshotValue = snapshot.val();
|
||||
});
|
||||
|
||||
await waitFor(() =>
|
||||
snapshotValue ? Promise.resolve(true) : Promise.reject(),
|
||||
);
|
||||
|
||||
expect(snapshotValue).not.toBeNull();
|
||||
expect(Object.keys(snapshotValue)).toHaveLength(2);
|
||||
Object.values(snapshotValue).forEach((resume) =>
|
||||
expect(resume.user).toEqual(DatabaseConstants.user1.uid),
|
||||
);
|
||||
});
|
||||
|
||||
it('previously set query parameters are not kept when retrieving reference again', () => {
|
||||
let reference = null;
|
||||
|
||||
reference = FirebaseStub.database().ref(DatabaseConstants.resumesPath);
|
||||
expect(reference).toBeTruthy();
|
||||
const { uuid } = reference;
|
||||
expect(reference.orderByChildPath).toHaveLength(0);
|
||||
expect(reference.equalToValue).toHaveLength(0);
|
||||
|
||||
reference = FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo('testuser1');
|
||||
expect(reference).toBeTruthy();
|
||||
expect(reference.uuid).toBe(uuid);
|
||||
expect(reference.orderByChildPath).toBe('user');
|
||||
expect(reference.equalToValue).toBe('testuser1');
|
||||
|
||||
reference = FirebaseStub.database().ref(DatabaseConstants.resumesPath);
|
||||
expect(reference).toBeTruthy();
|
||||
expect(reference.uuid).toBe(uuid);
|
||||
expect(reference.orderByChildPath).toHaveLength(0);
|
||||
expect(reference.equalToValue).toHaveLength(0);
|
||||
});
|
||||
|
||||
describe('set function', () => {
|
||||
it('inserts data', async () => {
|
||||
const existingResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(
|
||||
`${DatabaseConstants.resumesPath}/${DatabaseConstants.demoStateResume1Id}`,
|
||||
)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(existingResume).toBeTruthy();
|
||||
|
||||
const newResume = JSON.parse(JSON.stringify(existingResume));
|
||||
newResume.id = 'newre1';
|
||||
newResume.name = `Test Resume ${newResume.id}`;
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${newResume.id}`)
|
||||
.set(newResume);
|
||||
|
||||
const actualResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${newResume.id}`)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(actualResume).toBeTruthy();
|
||||
expect(actualResume).toEqual(newResume);
|
||||
});
|
||||
|
||||
it('triggers events', async () => {
|
||||
let snapshotValue = null;
|
||||
const callback = jest.fn((snapshot) => {
|
||||
snapshotValue = snapshot.val();
|
||||
});
|
||||
FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo(DatabaseConstants.user1.uid)
|
||||
.on('value', callback);
|
||||
await waitFor(() => callback.mock.calls[0][0]);
|
||||
callback.mockClear();
|
||||
snapshotValue = null;
|
||||
|
||||
const existingResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(
|
||||
`${DatabaseConstants.resumesPath}/${DatabaseConstants.demoStateResume1Id}`,
|
||||
)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(existingResume).toBeTruthy();
|
||||
|
||||
const newResume = JSON.parse(JSON.stringify(existingResume));
|
||||
newResume.id = 'newre1';
|
||||
newResume.name = `Test Resume ${newResume.id}`;
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${newResume.id}`)
|
||||
.set(newResume);
|
||||
|
||||
await waitFor(() => callback.mock.calls[0][0]);
|
||||
|
||||
expect(callback.mock.calls).toHaveLength(1);
|
||||
expect(snapshotValue).not.toBeNull();
|
||||
expect(Object.keys(snapshotValue)).toHaveLength(3);
|
||||
expect(snapshotValue[newResume.id]).toBeTruthy();
|
||||
expect(snapshotValue[newResume.id]).toEqual(newResume);
|
||||
});
|
||||
});
|
||||
|
||||
describe('update function', () => {
|
||||
it('can spy on it', async () => {
|
||||
const referencePath = `${DatabaseConstants.resumesPath}/123456`;
|
||||
const functionSpy = jest.spyOn(
|
||||
FirebaseStub.database().ref(referencePath),
|
||||
'update',
|
||||
);
|
||||
const updateArgument = 'test value 123';
|
||||
|
||||
await FirebaseStub.database().ref(referencePath).update(updateArgument);
|
||||
|
||||
expect(functionSpy).toHaveBeenCalledTimes(1);
|
||||
const functionCallArgument = functionSpy.mock.calls[0][0];
|
||||
expect(functionCallArgument).toBeTruthy();
|
||||
expect(functionCallArgument).toEqual(updateArgument);
|
||||
});
|
||||
|
||||
it('updates data', async () => {
|
||||
const resumeId = DatabaseConstants.demoStateResume1Id;
|
||||
const existingResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(existingResume).toBeTruthy();
|
||||
|
||||
const resumeName = 'Test Resume renamed';
|
||||
existingResume.name = resumeName;
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.update(existingResume);
|
||||
|
||||
const actualResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(actualResume).toBeTruthy();
|
||||
expect(existingResume).toEqual(actualResume);
|
||||
expect(actualResume.name).toEqual(resumeName);
|
||||
});
|
||||
|
||||
it('triggers events', async () => {
|
||||
let snapshotValue = null;
|
||||
const callback = jest.fn((snapshot) => {
|
||||
snapshotValue = snapshot.val();
|
||||
});
|
||||
FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo(DatabaseConstants.user1.uid)
|
||||
.on('value', callback);
|
||||
await waitFor(() => callback.mock.calls[0][0]);
|
||||
callback.mockClear();
|
||||
snapshotValue = null;
|
||||
|
||||
const existingResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(
|
||||
`${DatabaseConstants.resumesPath}/${DatabaseConstants.demoStateResume1Id}`,
|
||||
)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(existingResume).toBeTruthy();
|
||||
|
||||
existingResume.name = 'Test Resume renamed';
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${existingResume.id}`)
|
||||
.update(existingResume);
|
||||
|
||||
await waitFor(() => callback.mock.calls[0][0]);
|
||||
|
||||
expect(callback.mock.calls).toHaveLength(1);
|
||||
expect(snapshotValue).not.toBeNull();
|
||||
expect(Object.keys(snapshotValue)).toHaveLength(2);
|
||||
expect(snapshotValue[existingResume.id]).toBeTruthy();
|
||||
expect(snapshotValue[existingResume.id]).toEqual(existingResume);
|
||||
});
|
||||
});
|
||||
|
||||
describe('remove function', () => {
|
||||
it('deletes data', async () => {
|
||||
const resumeId = DatabaseConstants.demoStateResume1Id;
|
||||
const removedResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(removedResume).toBeTruthy();
|
||||
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.remove();
|
||||
|
||||
const actualResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(actualResume).toBeNull();
|
||||
});
|
||||
|
||||
it('triggers events', async () => {
|
||||
const userUid = DatabaseConstants.user1.uid;
|
||||
|
||||
let valueCallbackSnapshotValue = null;
|
||||
const valueCallback = jest.fn((snapshot) => {
|
||||
valueCallbackSnapshotValue = snapshot.val();
|
||||
});
|
||||
FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo(userUid)
|
||||
.on('value', valueCallback);
|
||||
await waitFor(() => valueCallback.mock.calls[0][0]);
|
||||
valueCallback.mockClear();
|
||||
valueCallbackSnapshotValue = null;
|
||||
|
||||
let childRemovedCallbackSnapshotValue = null;
|
||||
const childRemovedCallback = jest.fn((snapshot) => {
|
||||
childRemovedCallbackSnapshotValue = snapshot.val();
|
||||
});
|
||||
FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo(userUid)
|
||||
.on('child_removed', childRemovedCallback);
|
||||
|
||||
const removedResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(
|
||||
`${DatabaseConstants.resumesPath}/${DatabaseConstants.demoStateResume1Id}`,
|
||||
)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(removedResume).toBeTruthy();
|
||||
expect(removedResume.user).toEqual(userUid);
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${removedResume.id}`)
|
||||
.remove();
|
||||
|
||||
await waitFor(() => childRemovedCallback.mock.calls[0][0]);
|
||||
expect(childRemovedCallback.mock.calls).toHaveLength(1);
|
||||
expect(childRemovedCallbackSnapshotValue).toBeTruthy();
|
||||
expect(childRemovedCallbackSnapshotValue).toEqual(removedResume);
|
||||
|
||||
await waitFor(() => valueCallback.mock.calls[0][0]);
|
||||
expect(valueCallback.mock.calls).toHaveLength(1);
|
||||
expect(valueCallbackSnapshotValue).toBeTruthy();
|
||||
expect(removedResume.id in valueCallbackSnapshotValue).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('off function', () => {
|
||||
it('removes event callbacks', async () => {
|
||||
const userUid = DatabaseConstants.user1.uid;
|
||||
|
||||
let valueCallbackSnapshotValue = null;
|
||||
const valueCallback = jest.fn((snapshot) => {
|
||||
valueCallbackSnapshotValue = snapshot.val();
|
||||
});
|
||||
FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo(userUid)
|
||||
.on('value', valueCallback);
|
||||
await waitFor(() => valueCallback.mock.calls[0][0]);
|
||||
valueCallback.mockClear();
|
||||
valueCallbackSnapshotValue = null;
|
||||
|
||||
let childRemovedCallbackSnapshotValue = null;
|
||||
const childRemovedCallback = jest.fn((snapshot) => {
|
||||
childRemovedCallbackSnapshotValue = snapshot.val();
|
||||
});
|
||||
FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo(userUid)
|
||||
.on('child_removed', childRemovedCallback);
|
||||
|
||||
const removedResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(
|
||||
`${DatabaseConstants.resumesPath}/${DatabaseConstants.demoStateResume1Id}`,
|
||||
)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(removedResume).toBeTruthy();
|
||||
|
||||
FirebaseStub.database().ref(DatabaseConstants.resumesPath).off();
|
||||
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${removedResume.id}`)
|
||||
.remove();
|
||||
|
||||
expect(childRemovedCallback.mock.calls).toHaveLength(0);
|
||||
expect(childRemovedCallbackSnapshotValue).toBeNull();
|
||||
expect(valueCallback.mock.calls).toHaveLength(0);
|
||||
expect(valueCallbackSnapshotValue).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,51 @@
|
||||
import FirebaseStub, { AuthConstants } from '../../gatsby-plugin-firebase';
|
||||
|
||||
test('reuses existing Auth instance', () => {
|
||||
const auth1 = FirebaseStub.auth();
|
||||
const auth2 = FirebaseStub.auth();
|
||||
|
||||
expect(auth1.uuid).toBeTruthy();
|
||||
expect(auth2.uuid).toBeTruthy();
|
||||
expect(auth1.uuid).toEqual(auth2.uuid);
|
||||
});
|
||||
|
||||
test('returns anonymous user 1 when signing in anonymously', async () => {
|
||||
const user = await FirebaseStub.auth().signInAnonymously();
|
||||
|
||||
expect(user).toBeTruthy();
|
||||
expect(user).toEqual(AuthConstants.anonymousUser1);
|
||||
});
|
||||
|
||||
test('calls onAuthStateChanged observer with anonymous user 1 when signing in anonymously', async () => {
|
||||
let user = null;
|
||||
let error = null;
|
||||
FirebaseStub.auth().onAuthStateChanged(
|
||||
(_user) => {
|
||||
user = _user;
|
||||
},
|
||||
(_error) => {
|
||||
error = _error;
|
||||
},
|
||||
);
|
||||
|
||||
await FirebaseStub.auth().signInAnonymously();
|
||||
|
||||
expect(user).toBeTruthy();
|
||||
expect(user).toEqual(AuthConstants.anonymousUser1);
|
||||
expect(error).toBeNull();
|
||||
});
|
||||
|
||||
test('onAuthStateChanged unsubscribe removes observer', () => {
|
||||
const observer = () => {};
|
||||
const unsubscribe = FirebaseStub.auth().onAuthStateChanged(observer);
|
||||
expect(unsubscribe).toBeTruthy();
|
||||
expect(
|
||||
FirebaseStub.auth().onAuthStateChangedObservers.indexOf(observer),
|
||||
).toBeGreaterThanOrEqual(0);
|
||||
|
||||
unsubscribe();
|
||||
|
||||
expect(
|
||||
FirebaseStub.auth().onAuthStateChangedObservers.indexOf(observer),
|
||||
).not.toBeGreaterThanOrEqual(0);
|
||||
});
|
||||
@@ -0,0 +1,53 @@
|
||||
import { waitFor } from '@testing-library/react';
|
||||
import FirebaseStub, { DatabaseConstants } from '../../gatsby-plugin-firebase';
|
||||
|
||||
test('can filter resumes by user', async () => {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
let snapshotValue = null;
|
||||
|
||||
FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo(DatabaseConstants.user1.uid)
|
||||
.on('value', (snapshot) => {
|
||||
snapshotValue = snapshot.val();
|
||||
});
|
||||
|
||||
await waitFor(() =>
|
||||
snapshotValue ? Promise.resolve(true) : Promise.reject(),
|
||||
);
|
||||
|
||||
expect(snapshotValue).not.toBeNull();
|
||||
expect(Object.keys(snapshotValue)).toHaveLength(2);
|
||||
Object.values(snapshotValue).forEach((resume) =>
|
||||
expect(resume.user).toEqual(DatabaseConstants.user1.uid),
|
||||
);
|
||||
});
|
||||
|
||||
test('previously set query parameters are not kept when retrieving reference again', () => {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
let reference = null;
|
||||
|
||||
reference = FirebaseStub.database().ref(DatabaseConstants.resumesPath);
|
||||
expect(reference).toBeTruthy();
|
||||
const { uuid } = reference;
|
||||
expect(reference.orderByChildPath).toHaveLength(0);
|
||||
expect(reference.equalToValue).toHaveLength(0);
|
||||
|
||||
reference = FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo('testuser1');
|
||||
expect(reference).toBeTruthy();
|
||||
expect(reference.uuid).toBe(uuid);
|
||||
expect(reference.orderByChildPath).toBe('user');
|
||||
expect(reference.equalToValue).toBe('testuser1');
|
||||
|
||||
reference = FirebaseStub.database().ref(DatabaseConstants.resumesPath);
|
||||
expect(reference).toBeTruthy();
|
||||
expect(reference.uuid).toBe(uuid);
|
||||
expect(reference.orderByChildPath).toHaveLength(0);
|
||||
expect(reference.equalToValue).toHaveLength(0);
|
||||
});
|
||||
@@ -0,0 +1,51 @@
|
||||
import { waitFor } from '@testing-library/react';
|
||||
import FirebaseStub, { DatabaseConstants } from '../../gatsby-plugin-firebase';
|
||||
|
||||
test('removes event callbacks', async () => {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
const userUid = DatabaseConstants.user1.uid;
|
||||
|
||||
let valueCallbackSnapshotValue = null;
|
||||
const valueCallback = jest.fn((snapshot) => {
|
||||
valueCallbackSnapshotValue = snapshot.val();
|
||||
});
|
||||
FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo(userUid)
|
||||
.on('value', valueCallback);
|
||||
await waitFor(() => valueCallback.mock.calls[0][0]);
|
||||
valueCallback.mockClear();
|
||||
valueCallbackSnapshotValue = null;
|
||||
|
||||
let childRemovedCallbackSnapshotValue = null;
|
||||
const childRemovedCallback = jest.fn((snapshot) => {
|
||||
childRemovedCallbackSnapshotValue = snapshot.val();
|
||||
});
|
||||
FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo(userUid)
|
||||
.on('child_removed', childRemovedCallback);
|
||||
|
||||
const removedResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(
|
||||
`${DatabaseConstants.resumesPath}/${DatabaseConstants.demoStateResume1Id}`,
|
||||
)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(removedResume).toBeTruthy();
|
||||
|
||||
FirebaseStub.database().ref(DatabaseConstants.resumesPath).off();
|
||||
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${removedResume.id}`)
|
||||
.remove();
|
||||
|
||||
expect(childRemovedCallback.mock.calls).toHaveLength(0);
|
||||
expect(childRemovedCallbackSnapshotValue).toBeNull();
|
||||
expect(valueCallback.mock.calls).toHaveLength(0);
|
||||
expect(valueCallbackSnapshotValue).toBeNull();
|
||||
});
|
||||
@@ -0,0 +1,45 @@
|
||||
import { waitFor } from '@testing-library/react';
|
||||
import FirebaseStub, { DatabaseConstants } from '../../gatsby-plugin-firebase';
|
||||
|
||||
test('triggers event with true if on the connected reference path', async () => {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
let snapshotValue = null;
|
||||
|
||||
FirebaseStub.database()
|
||||
.ref(DatabaseConstants.connectedPath)
|
||||
.on('value', (snapshot) => {
|
||||
snapshotValue = snapshot.val();
|
||||
});
|
||||
|
||||
await waitFor(() =>
|
||||
snapshotValue ? Promise.resolve(true) : Promise.reject(),
|
||||
);
|
||||
|
||||
expect(snapshotValue).not.toBeNull();
|
||||
expect(snapshotValue).toBe(true);
|
||||
});
|
||||
|
||||
test('triggers event with resumes if on the resumes reference path', async () => {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
const resumesDataSnapshot = await FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.once('value');
|
||||
const resumes = resumesDataSnapshot.val();
|
||||
|
||||
let snapshotValue = null;
|
||||
|
||||
FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.on('value', (snapshot) => {
|
||||
snapshotValue = snapshot.val();
|
||||
});
|
||||
|
||||
await waitFor(() =>
|
||||
snapshotValue ? Promise.resolve(true) : Promise.reject(),
|
||||
);
|
||||
|
||||
expect(snapshotValue).not.toBeNull();
|
||||
expect(snapshotValue).toEqual(resumes);
|
||||
});
|
||||
@@ -0,0 +1,59 @@
|
||||
import FirebaseStub, { DatabaseConstants } from '../../gatsby-plugin-firebase';
|
||||
|
||||
test('retrieves resume if it exists', async () => {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
const resumeId = DatabaseConstants.demoStateResume1Id;
|
||||
|
||||
const resume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.once('value')
|
||||
).val();
|
||||
|
||||
expect(resume).toBeTruthy();
|
||||
expect(resume.id).toEqual(resumeId);
|
||||
});
|
||||
|
||||
test('retrieves null if resume does not exist', async () => {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
const resumeId = 'invalidResumeId';
|
||||
|
||||
const resume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.once('value')
|
||||
).val();
|
||||
|
||||
expect(resume).toBeNull();
|
||||
});
|
||||
|
||||
test('retrieves user if it exists', async () => {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
const expectedUser = DatabaseConstants.user1;
|
||||
|
||||
const user = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.usersPath}/${expectedUser.uid}`)
|
||||
.once('value')
|
||||
).val();
|
||||
|
||||
expect(user).toBeTruthy();
|
||||
expect(user).toEqual(expectedUser);
|
||||
});
|
||||
|
||||
test('retrieves null if user does not exist', async () => {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
const userId = 'invalidUserId';
|
||||
|
||||
const user = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.usersPath}/${userId}`)
|
||||
.once('value')
|
||||
).val();
|
||||
|
||||
expect(user).toBeNull();
|
||||
});
|
||||
@@ -0,0 +1,77 @@
|
||||
import { waitFor } from '@testing-library/react';
|
||||
import FirebaseStub, { DatabaseConstants } from '../../gatsby-plugin-firebase';
|
||||
|
||||
test('deletes data', async () => {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
const resumeId = DatabaseConstants.demoStateResume1Id;
|
||||
const removedResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(removedResume).toBeTruthy();
|
||||
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.remove();
|
||||
|
||||
const actualResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(actualResume).toBeNull();
|
||||
});
|
||||
|
||||
test('triggers events', async () => {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
const userUid = DatabaseConstants.user1.uid;
|
||||
|
||||
let valueCallbackSnapshotValue = null;
|
||||
const valueCallback = jest.fn((snapshot) => {
|
||||
valueCallbackSnapshotValue = snapshot.val();
|
||||
});
|
||||
FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo(userUid)
|
||||
.on('value', valueCallback);
|
||||
await waitFor(() => valueCallback.mock.calls[0][0]);
|
||||
valueCallback.mockClear();
|
||||
valueCallbackSnapshotValue = null;
|
||||
|
||||
let childRemovedCallbackSnapshotValue = null;
|
||||
const childRemovedCallback = jest.fn((snapshot) => {
|
||||
childRemovedCallbackSnapshotValue = snapshot.val();
|
||||
});
|
||||
FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo(userUid)
|
||||
.on('child_removed', childRemovedCallback);
|
||||
|
||||
const removedResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(
|
||||
`${DatabaseConstants.resumesPath}/${DatabaseConstants.demoStateResume1Id}`,
|
||||
)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(removedResume).toBeTruthy();
|
||||
expect(removedResume.user).toEqual(userUid);
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${removedResume.id}`)
|
||||
.remove();
|
||||
|
||||
await waitFor(() => childRemovedCallback.mock.calls[0][0]);
|
||||
expect(childRemovedCallback.mock.calls).toHaveLength(1);
|
||||
expect(childRemovedCallbackSnapshotValue).toBeTruthy();
|
||||
expect(childRemovedCallbackSnapshotValue).toEqual(removedResume);
|
||||
|
||||
await waitFor(() => valueCallback.mock.calls[0][0]);
|
||||
expect(valueCallback.mock.calls).toHaveLength(1);
|
||||
expect(valueCallbackSnapshotValue).toBeTruthy();
|
||||
expect(removedResume.id in valueCallbackSnapshotValue).toBe(false);
|
||||
});
|
||||
@@ -0,0 +1,71 @@
|
||||
import { waitFor } from '@testing-library/react';
|
||||
import FirebaseStub, { DatabaseConstants } from '../../gatsby-plugin-firebase';
|
||||
|
||||
test('inserts data', async () => {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
const existingResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(
|
||||
`${DatabaseConstants.resumesPath}/${DatabaseConstants.demoStateResume1Id}`,
|
||||
)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(existingResume).toBeTruthy();
|
||||
|
||||
const newResume = JSON.parse(JSON.stringify(existingResume));
|
||||
newResume.id = 'newre1';
|
||||
newResume.name = `Test Resume ${newResume.id}`;
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${newResume.id}`)
|
||||
.set(newResume);
|
||||
|
||||
const actualResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${newResume.id}`)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(actualResume).toBeTruthy();
|
||||
expect(actualResume).toEqual(newResume);
|
||||
});
|
||||
|
||||
test('triggers events', async () => {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
let snapshotValue = null;
|
||||
const callback = jest.fn((snapshot) => {
|
||||
snapshotValue = snapshot.val();
|
||||
});
|
||||
FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo(DatabaseConstants.user1.uid)
|
||||
.on('value', callback);
|
||||
await waitFor(() => callback.mock.calls[0][0]);
|
||||
callback.mockClear();
|
||||
snapshotValue = null;
|
||||
|
||||
const existingResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(
|
||||
`${DatabaseConstants.resumesPath}/${DatabaseConstants.demoStateResume1Id}`,
|
||||
)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(existingResume).toBeTruthy();
|
||||
|
||||
const newResume = JSON.parse(JSON.stringify(existingResume));
|
||||
newResume.id = 'newre1';
|
||||
newResume.name = `Test Resume ${newResume.id}`;
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${newResume.id}`)
|
||||
.set(newResume);
|
||||
|
||||
await waitFor(() => callback.mock.calls[0][0]);
|
||||
|
||||
expect(callback.mock.calls).toHaveLength(1);
|
||||
expect(snapshotValue).not.toBeNull();
|
||||
expect(Object.keys(snapshotValue)).toHaveLength(3);
|
||||
expect(snapshotValue[newResume.id]).toBeTruthy();
|
||||
expect(snapshotValue[newResume.id]).toEqual(newResume);
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
import FirebaseStub, { DatabaseConstants } from '../../gatsby-plugin-firebase';
|
||||
|
||||
test('reuses existing Reference instance', () => {
|
||||
const ref1 = FirebaseStub.database().ref(
|
||||
`${DatabaseConstants.resumesPath}/123`,
|
||||
);
|
||||
const ref2 = FirebaseStub.database().ref(
|
||||
`${DatabaseConstants.resumesPath}/123`,
|
||||
);
|
||||
|
||||
expect(ref1).toBeTruthy();
|
||||
expect(ref2).toBeTruthy();
|
||||
expect(ref1).toEqual(ref2);
|
||||
});
|
||||
|
||||
test('leading slash in reference path is ignored', () => {
|
||||
const path = `${DatabaseConstants.resumesPath}/123`;
|
||||
|
||||
const ref1 = FirebaseStub.database().ref(path);
|
||||
expect(ref1).toBeTruthy();
|
||||
expect(ref1.path).toEqual(path);
|
||||
|
||||
const ref2 = FirebaseStub.database().ref(`/${path}`);
|
||||
expect(ref2).toBeTruthy();
|
||||
expect(ref2).toEqual(ref1);
|
||||
});
|
||||
@@ -0,0 +1,86 @@
|
||||
import { waitFor } from '@testing-library/react';
|
||||
import FirebaseStub, { DatabaseConstants } from '../../gatsby-plugin-firebase';
|
||||
|
||||
test('can spy on it', async () => {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
const referencePath = `${DatabaseConstants.resumesPath}/123456`;
|
||||
const functionSpy = jest.spyOn(
|
||||
FirebaseStub.database().ref(referencePath),
|
||||
'update',
|
||||
);
|
||||
const updateArgument = 'test value 123';
|
||||
|
||||
await FirebaseStub.database().ref(referencePath).update(updateArgument);
|
||||
|
||||
expect(functionSpy).toHaveBeenCalledTimes(1);
|
||||
const functionCallArgument = functionSpy.mock.calls[0][0];
|
||||
expect(functionCallArgument).toBeTruthy();
|
||||
expect(functionCallArgument).toEqual(updateArgument);
|
||||
});
|
||||
|
||||
test('updates data', async () => {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
const resumeId = DatabaseConstants.demoStateResume1Id;
|
||||
const existingResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(existingResume).toBeTruthy();
|
||||
|
||||
const resumeName = 'Test Resume renamed';
|
||||
existingResume.name = resumeName;
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.update(existingResume);
|
||||
|
||||
const actualResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(actualResume).toBeTruthy();
|
||||
expect(existingResume).toEqual(actualResume);
|
||||
expect(actualResume.name).toEqual(resumeName);
|
||||
});
|
||||
|
||||
test('triggers events', async () => {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
let snapshotValue = null;
|
||||
const callback = jest.fn((snapshot) => {
|
||||
snapshotValue = snapshot.val();
|
||||
});
|
||||
FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo(DatabaseConstants.user1.uid)
|
||||
.on('value', callback);
|
||||
await waitFor(() => callback.mock.calls[0][0]);
|
||||
callback.mockClear();
|
||||
snapshotValue = null;
|
||||
|
||||
const existingResume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(
|
||||
`${DatabaseConstants.resumesPath}/${DatabaseConstants.demoStateResume1Id}`,
|
||||
)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(existingResume).toBeTruthy();
|
||||
|
||||
existingResume.name = 'Test Resume renamed';
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${existingResume.id}`)
|
||||
.update(existingResume);
|
||||
|
||||
await waitFor(() => callback.mock.calls[0][0]);
|
||||
|
||||
expect(callback.mock.calls).toHaveLength(1);
|
||||
expect(snapshotValue).not.toBeNull();
|
||||
expect(Object.keys(snapshotValue)).toHaveLength(2);
|
||||
expect(snapshotValue[existingResume.id]).toBeTruthy();
|
||||
expect(snapshotValue[existingResume.id]).toEqual(existingResume);
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
import FirebaseStub, { DatabaseConstants } from '../../gatsby-plugin-firebase';
|
||||
|
||||
test('reuses existing Database instance', () => {
|
||||
const database1 = FirebaseStub.database();
|
||||
const database2 = FirebaseStub.database();
|
||||
|
||||
expect(database1.uuid).toBeTruthy();
|
||||
expect(database2.uuid).toBeTruthy();
|
||||
expect(database1.uuid).toEqual(database2.uuid);
|
||||
});
|
||||
|
||||
test('ServerValue.TIMESTAMP returns current time in milliseconds', () => {
|
||||
const now = new Date().getTime();
|
||||
const timestamp = FirebaseStub.database.ServerValue.TIMESTAMP;
|
||||
|
||||
expect(timestamp).toBeTruthy();
|
||||
expect(timestamp).toBeGreaterThanOrEqual(now);
|
||||
});
|
||||
|
||||
test('initializing data sets up resumes and users', async () => {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
const resumesRef = FirebaseStub.database().ref(DatabaseConstants.resumesPath);
|
||||
const resumesDataSnapshot = await resumesRef.once('value');
|
||||
const resumes = resumesDataSnapshot.val();
|
||||
expect(resumes).toBeTruthy();
|
||||
expect(Object.keys(resumes)).toHaveLength(3);
|
||||
const demoStateResume1 = resumes[DatabaseConstants.demoStateResume1Id];
|
||||
expect(demoStateResume1).toBeTruthy();
|
||||
expect(demoStateResume1.id).toEqual(DatabaseConstants.demoStateResume1Id);
|
||||
expect(demoStateResume1.user).toEqual(DatabaseConstants.user1.uid);
|
||||
const demoStateResume2 = resumes[DatabaseConstants.demoStateResume2Id];
|
||||
expect(demoStateResume2).toBeTruthy();
|
||||
expect(demoStateResume2.id).toEqual(DatabaseConstants.demoStateResume2Id);
|
||||
expect(demoStateResume2.user).toEqual(DatabaseConstants.user2.uid);
|
||||
const initialStateResume = resumes[DatabaseConstants.initialStateResumeId];
|
||||
expect(initialStateResume).toBeTruthy();
|
||||
expect(initialStateResume.id).toEqual(DatabaseConstants.initialStateResumeId);
|
||||
expect(initialStateResume.user).toEqual(DatabaseConstants.user1.uid);
|
||||
|
||||
const usersRef = FirebaseStub.database().ref(DatabaseConstants.usersPath);
|
||||
const usersDataSnapshot = await usersRef.once('value');
|
||||
const users = usersDataSnapshot.val();
|
||||
expect(users).toBeTruthy();
|
||||
expect(Object.keys(users)).toHaveLength(2);
|
||||
const anonymousUser1 = users[DatabaseConstants.user1.uid];
|
||||
expect(anonymousUser1).toBeTruthy();
|
||||
expect(anonymousUser1).toEqual(DatabaseConstants.user1);
|
||||
const anonymousUser2 = users[DatabaseConstants.user2.uid];
|
||||
expect(anonymousUser2).toBeTruthy();
|
||||
expect(anonymousUser2).toEqual(DatabaseConstants.user2);
|
||||
});
|
||||
@@ -2,7 +2,7 @@
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import Constants from '../constants/auth';
|
||||
import delay from '../../utils/index';
|
||||
import { delay } from '../../../src/utils/index';
|
||||
|
||||
const singleton = Symbol('');
|
||||
const singletonEnforcer = Symbol('');
|
||||
@@ -50,7 +50,7 @@ class Auth {
|
||||
|
||||
this.onAuthStateChangedObservers.forEach((observer) => observer(user));
|
||||
|
||||
return Promise.resolve(user);
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import DatabaseConstants from '../constants/database';
|
||||
import DataSnapshot from './dataSnapshot';
|
||||
import delay from '../../utils/index';
|
||||
import { delay } from '../../../src/utils/index';
|
||||
|
||||
const parsePath = (path) => {
|
||||
if (!path) {
|
||||
@@ -185,7 +185,7 @@ class Reference {
|
||||
|
||||
await delay(DatabaseConstants.defaultDelayInMilliseconds);
|
||||
|
||||
return Promise.resolve(this._dataSnapshot);
|
||||
return this._dataSnapshot;
|
||||
}
|
||||
|
||||
orderByChild(path) {
|
||||
@@ -197,24 +197,18 @@ class Reference {
|
||||
await delay(DatabaseConstants.defaultDelayInMilliseconds);
|
||||
|
||||
this._handleDataUpdate(value);
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
async remove() {
|
||||
await delay(DatabaseConstants.defaultDelayInMilliseconds);
|
||||
|
||||
this._handleDataUpdate(null);
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
async set(value) {
|
||||
await delay(DatabaseConstants.defaultDelayInMilliseconds);
|
||||
|
||||
this._handleDataUpdate(value);
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
import delay from './utils/index';
|
||||
import { delay } from '../src/utils/index';
|
||||
|
||||
const Gatsby = jest.requireActual('gatsby');
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
const delay = async (milliseconds) => {
|
||||
await new Promise((resolve) => setTimeout(resolve, milliseconds));
|
||||
};
|
||||
|
||||
export default delay;
|
||||
@@ -1 +1,4 @@
|
||||
import '@testing-library/jest-dom/extend-expect';
|
||||
import fetchMock from 'jest-fetch-mock';
|
||||
|
||||
fetchMock.enableMocks();
|
||||
|
||||
Generated
+10
@@ -16432,6 +16432,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"jest-fetch-mock": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz",
|
||||
"integrity": "sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cross-fetch": "^3.0.4",
|
||||
"promise-polyfill": "^8.1.3"
|
||||
}
|
||||
},
|
||||
"jest-get-type": {
|
||||
"version": "25.2.6",
|
||||
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz",
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
"gatsby-plugin-eslint": "^2.0.8",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"jest": "^26.6.3",
|
||||
"jest-fetch-mock": "^3.0.3",
|
||||
"prettier": "2.2.1",
|
||||
"stylelint": "^13.9.0",
|
||||
"stylelint-config-standard": "^20.0.0",
|
||||
|
||||
@@ -5,6 +5,8 @@ import ModalContext from '../../contexts/ModalContext';
|
||||
import { handleKeyUp } from '../../utils';
|
||||
import styles from './CreateResume.module.css';
|
||||
|
||||
const createResumeButtonDataTestId = 'create-resume-button';
|
||||
|
||||
const CreateResume = () => {
|
||||
const { t } = useTranslation();
|
||||
const { emitter, events } = useContext(ModalContext);
|
||||
@@ -17,6 +19,7 @@ const CreateResume = () => {
|
||||
<MdAdd size="48" />
|
||||
</div>
|
||||
<div
|
||||
data-testid={createResumeButtonDataTestId}
|
||||
tabIndex="0"
|
||||
role="button"
|
||||
className={styles.page}
|
||||
@@ -33,3 +36,5 @@ const CreateResume = () => {
|
||||
};
|
||||
|
||||
export default memo(CreateResume);
|
||||
|
||||
export { createResumeButtonDataTestId };
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import { fireEvent, screen } from '@testing-library/react';
|
||||
|
||||
import { DatabaseConstants } from 'gatsby-plugin-firebase';
|
||||
|
||||
import {
|
||||
setupAndWait,
|
||||
expectDatabaseUpdateToHaveCompleted,
|
||||
} from './helpers/builder';
|
||||
|
||||
const testTimeoutInMilliseconds = 20000;
|
||||
jest.setTimeout(testTimeoutInMilliseconds);
|
||||
|
||||
test('when input value is changed, updates database', async () => {
|
||||
const resumeId = DatabaseConstants.demoStateResume1Id;
|
||||
const { mockDatabaseUpdateFunction } = await setupAndWait(
|
||||
resumeId,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
|
||||
const input = screen.getByRole('textbox', { name: /address line 1/i });
|
||||
const newInputValue = 'test street 123';
|
||||
const now = new Date().getTime();
|
||||
|
||||
fireEvent.change(input, { target: { value: newInputValue } });
|
||||
|
||||
expect(input.value).toBe(newInputValue);
|
||||
|
||||
await expectDatabaseUpdateToHaveCompleted(mockDatabaseUpdateFunction);
|
||||
const mockDatabaseUpdateFunctionCallArgument =
|
||||
mockDatabaseUpdateFunction.mock.calls[0][0];
|
||||
expect(mockDatabaseUpdateFunctionCallArgument.id).toBe(resumeId);
|
||||
expect(mockDatabaseUpdateFunctionCallArgument.profile.address.line1).toBe(
|
||||
newInputValue,
|
||||
);
|
||||
expect(
|
||||
mockDatabaseUpdateFunctionCallArgument.updatedAt,
|
||||
).toBeGreaterThanOrEqual(now);
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
import { navigate as mockNavigateFunction } from 'gatsby';
|
||||
import { fireEvent, getByText, screen, waitFor } from '@testing-library/react';
|
||||
|
||||
import setup from './helpers/builder';
|
||||
|
||||
test('if resume does not exist, navigates to Dashboard and displays notification', async () => {
|
||||
await setup('xxxxxx');
|
||||
|
||||
await waitFor(() => expect(mockNavigateFunction).toHaveBeenCalledTimes(1));
|
||||
expect(mockNavigateFunction).toHaveBeenCalledWith('/app/dashboard');
|
||||
|
||||
const notification = await screen.findByRole('alert');
|
||||
expect(
|
||||
getByText(
|
||||
notification,
|
||||
/The resume you were looking for does not exist anymore/i,
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
fireEvent.click(notification);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(mockNavigateFunction.mock.results[0].value).resolves.toBeUndefined(),
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,63 @@
|
||||
import {
|
||||
fireEvent,
|
||||
getByText,
|
||||
screen,
|
||||
waitForElementToBeRemoved,
|
||||
} from '@testing-library/react';
|
||||
|
||||
import { DatabaseConstants } from 'gatsby-plugin-firebase';
|
||||
|
||||
import { dataTestId as loadingScreenTestId } from '../../../components/router/LoadingScreen';
|
||||
|
||||
import setup, {
|
||||
setupAndWait,
|
||||
waitForDatabaseUpdateToHaveCompleted,
|
||||
} from './helpers/builder';
|
||||
|
||||
const testTimeoutInMilliseconds = 10000;
|
||||
jest.setTimeout(testTimeoutInMilliseconds);
|
||||
|
||||
test('renders first and last name', async () => {
|
||||
const { resume } = await setupAndWait(
|
||||
DatabaseConstants.demoStateResume1Id,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
|
||||
expect(
|
||||
screen.getByRole('textbox', { name: /first name/i }),
|
||||
).toHaveDisplayValue(resume.profile.firstName);
|
||||
expect(
|
||||
screen.getByRole('textbox', { name: /last name/i }),
|
||||
).toHaveDisplayValue(resume.profile.lastName);
|
||||
expect(
|
||||
screen.getAllByText(new RegExp(resume.profile.firstName, 'i')).length,
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
screen.getAllByText(new RegExp(resume.profile.lastName, 'i')).length,
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
test('renders loading screen', async () => {
|
||||
const { mockDatabaseUpdateFunction } = await setup(
|
||||
DatabaseConstants.demoStateResume1Id,
|
||||
);
|
||||
|
||||
expect(screen.getByTestId(loadingScreenTestId)).toBeInTheDocument();
|
||||
|
||||
await waitForElementToBeRemoved(() =>
|
||||
screen.getByTestId(loadingScreenTestId),
|
||||
);
|
||||
|
||||
await waitForDatabaseUpdateToHaveCompleted(mockDatabaseUpdateFunction);
|
||||
});
|
||||
|
||||
test('if resume is in initial state, renders load demo data notification', async () => {
|
||||
await setup(DatabaseConstants.initialStateResumeId);
|
||||
|
||||
const notification = await screen.findByRole('alert');
|
||||
expect(
|
||||
getByText(notification, /Not sure where to begin\? Try loading demo data/i),
|
||||
).toBeInTheDocument();
|
||||
fireEvent.click(notification);
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
import { fireEvent, screen } from '@testing-library/react';
|
||||
|
||||
import { DatabaseConstants } from 'gatsby-plugin-firebase';
|
||||
|
||||
import { languageStorageItemKey } from '../../../contexts/SettingsContext';
|
||||
|
||||
import {
|
||||
setupAndWait,
|
||||
expectDatabaseUpdateToHaveCompleted,
|
||||
} from './helpers/builder';
|
||||
|
||||
const testTimeoutInMilliseconds = 20000;
|
||||
jest.setTimeout(testTimeoutInMilliseconds);
|
||||
|
||||
test('allows to change the language', async () => {
|
||||
const resumeId = DatabaseConstants.demoStateResume1Id;
|
||||
const { mockDatabaseUpdateFunction } = await setupAndWait(
|
||||
resumeId,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
|
||||
const languageElement = screen.getByLabelText(/language/i);
|
||||
const italianLanguageCode = 'it';
|
||||
const now = new Date().getTime();
|
||||
|
||||
fireEvent.change(languageElement, {
|
||||
target: { value: italianLanguageCode },
|
||||
});
|
||||
|
||||
expect(languageElement).toHaveValue(italianLanguageCode);
|
||||
|
||||
expect(screen.queryByLabelText(/date of birth/i)).not.toBeInTheDocument();
|
||||
expect(screen.getByLabelText(/data di nascita/i)).toBeInTheDocument();
|
||||
|
||||
const languageStorageItem = localStorage.getItem(languageStorageItemKey);
|
||||
expect(languageStorageItem).toBe(italianLanguageCode);
|
||||
|
||||
await expectDatabaseUpdateToHaveCompleted(mockDatabaseUpdateFunction);
|
||||
const mockDatabaseUpdateFunctionCallArgument =
|
||||
mockDatabaseUpdateFunction.mock.calls[0][0];
|
||||
expect(mockDatabaseUpdateFunctionCallArgument.id).toBe(resumeId);
|
||||
expect(mockDatabaseUpdateFunctionCallArgument.metadata.language).toBe(
|
||||
italianLanguageCode,
|
||||
);
|
||||
expect(
|
||||
mockDatabaseUpdateFunctionCallArgument.updatedAt,
|
||||
).toBeGreaterThanOrEqual(now);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
const englishLanguageCode = 'en';
|
||||
localStorage.setItem(languageStorageItemKey, englishLanguageCode);
|
||||
});
|
||||
@@ -1,259 +0,0 @@
|
||||
import { navigate as mockNavigateFunction } from 'gatsby';
|
||||
import React from 'react';
|
||||
import {
|
||||
fireEvent,
|
||||
getByText,
|
||||
render,
|
||||
screen,
|
||||
waitFor,
|
||||
waitForElementToBeRemoved,
|
||||
} from '@testing-library/react';
|
||||
|
||||
import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase';
|
||||
|
||||
import { dataTestId as loadingScreenTestId } from '../../../components/router/LoadingScreen';
|
||||
import {
|
||||
SettingsProvider,
|
||||
languageStorageItemKey,
|
||||
} from '../../../contexts/SettingsContext';
|
||||
import { ModalProvider } from '../../../contexts/ModalContext';
|
||||
import { UserProvider } from '../../../contexts/UserContext';
|
||||
import {
|
||||
DatabaseProvider,
|
||||
DebounceWaitTime,
|
||||
} from '../../../contexts/DatabaseContext';
|
||||
import { ResumeProvider } from '../../../contexts/ResumeContext';
|
||||
import { StorageProvider } from '../../../contexts/StorageContext';
|
||||
import Wrapper from '../../../components/shared/Wrapper';
|
||||
import Builder from '../builder';
|
||||
|
||||
describe('Builder', () => {
|
||||
let resumeId = null;
|
||||
let resume = null;
|
||||
let mockDatabaseUpdateFunction = null;
|
||||
|
||||
const fnWaitForDatabaseUpdateToHaveCompleted = async () => {
|
||||
await waitFor(() => mockDatabaseUpdateFunction.mock.calls[0][0], {
|
||||
timeout: DebounceWaitTime,
|
||||
});
|
||||
await waitFor(() => mockDatabaseUpdateFunction.mock.results[0].value);
|
||||
};
|
||||
|
||||
const expectDatabaseUpdateToHaveCompleted = async () => {
|
||||
await waitFor(
|
||||
() => expect(mockDatabaseUpdateFunction).toHaveBeenCalledTimes(1),
|
||||
{
|
||||
timeout: DebounceWaitTime,
|
||||
},
|
||||
);
|
||||
await waitFor(() =>
|
||||
expect(
|
||||
mockDatabaseUpdateFunction.mock.results[0].value,
|
||||
).resolves.toBeUndefined(),
|
||||
);
|
||||
};
|
||||
|
||||
async function setup(
|
||||
resumeIdParameter,
|
||||
waitForLoadingScreenToDisappear = true,
|
||||
waitForDatabaseUpdateToHaveCompleted = true,
|
||||
) {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
resumeId = resumeIdParameter;
|
||||
resume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.once('value')
|
||||
).val();
|
||||
|
||||
mockDatabaseUpdateFunction = jest.spyOn(
|
||||
FirebaseStub.database().ref(
|
||||
`${DatabaseConstants.resumesPath}/${resumeId}`,
|
||||
),
|
||||
'update',
|
||||
);
|
||||
|
||||
FirebaseStub.auth().signInAnonymously();
|
||||
|
||||
render(
|
||||
<SettingsProvider>
|
||||
<ModalProvider>
|
||||
<UserProvider>
|
||||
<DatabaseProvider>
|
||||
<ResumeProvider>
|
||||
<StorageProvider>
|
||||
<Wrapper>
|
||||
<Builder id={resumeId} />
|
||||
</Wrapper>
|
||||
</StorageProvider>
|
||||
</ResumeProvider>
|
||||
</DatabaseProvider>
|
||||
</UserProvider>
|
||||
</ModalProvider>
|
||||
</SettingsProvider>,
|
||||
);
|
||||
|
||||
if (waitForLoadingScreenToDisappear) {
|
||||
await waitForElementToBeRemoved(() =>
|
||||
screen.getByTestId(loadingScreenTestId),
|
||||
);
|
||||
}
|
||||
|
||||
if (waitForDatabaseUpdateToHaveCompleted) {
|
||||
await fnWaitForDatabaseUpdateToHaveCompleted();
|
||||
mockDatabaseUpdateFunction.mockClear();
|
||||
}
|
||||
}
|
||||
|
||||
describe('handles errors', () => {
|
||||
describe('if resume does not exist', () => {
|
||||
beforeEach(async () => {
|
||||
await setup('xxxxxx', false, false);
|
||||
});
|
||||
|
||||
it('navigates to Dashboard and displays notification', async () => {
|
||||
await waitFor(() =>
|
||||
expect(mockNavigateFunction).toHaveBeenCalledTimes(1),
|
||||
);
|
||||
expect(mockNavigateFunction).toHaveBeenCalledWith('/app/dashboard');
|
||||
|
||||
const notification = await screen.findByRole('alert');
|
||||
expect(
|
||||
getByText(
|
||||
notification,
|
||||
/The resume you were looking for does not exist anymore/i,
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
fireEvent.click(notification);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(
|
||||
mockNavigateFunction.mock.results[0].value,
|
||||
).resolves.toBeUndefined(),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('renders', () => {
|
||||
beforeEach(async () => {
|
||||
await setup(DatabaseConstants.demoStateResume1Id);
|
||||
});
|
||||
|
||||
it('first and last name', () => {
|
||||
expect(
|
||||
screen.getByRole('textbox', { name: /first name/i }),
|
||||
).toHaveDisplayValue(resume.profile.firstName);
|
||||
expect(
|
||||
screen.getByRole('textbox', { name: /last name/i }),
|
||||
).toHaveDisplayValue(resume.profile.lastName);
|
||||
expect(
|
||||
screen.getAllByText(new RegExp(resume.profile.firstName, 'i')).length,
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
screen.getAllByText(new RegExp(resume.profile.lastName, 'i')).length,
|
||||
).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('settings', () => {
|
||||
beforeEach(async () => {
|
||||
await setup(DatabaseConstants.demoStateResume1Id);
|
||||
});
|
||||
|
||||
it('allow to change the language', async () => {
|
||||
const languageElement = screen.getByLabelText(/language/i);
|
||||
const italianLanguageCode = 'it';
|
||||
const now = new Date().getTime();
|
||||
|
||||
fireEvent.change(languageElement, {
|
||||
target: { value: italianLanguageCode },
|
||||
});
|
||||
|
||||
expect(languageElement).toHaveValue(italianLanguageCode);
|
||||
|
||||
expect(screen.queryByLabelText(/date of birth/i)).not.toBeInTheDocument();
|
||||
expect(screen.getByLabelText(/data di nascita/i)).toBeInTheDocument();
|
||||
|
||||
const languageStorageItem = localStorage.getItem(languageStorageItemKey);
|
||||
expect(languageStorageItem).toBe(italianLanguageCode);
|
||||
|
||||
await expectDatabaseUpdateToHaveCompleted();
|
||||
const mockDatabaseUpdateFunctionCallArgument =
|
||||
mockDatabaseUpdateFunction.mock.calls[0][0];
|
||||
expect(mockDatabaseUpdateFunctionCallArgument.id).toBe(resumeId);
|
||||
expect(mockDatabaseUpdateFunctionCallArgument.metadata.language).toBe(
|
||||
italianLanguageCode,
|
||||
);
|
||||
expect(
|
||||
mockDatabaseUpdateFunctionCallArgument.updatedAt,
|
||||
).toBeGreaterThanOrEqual(now);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
const englishLanguageCode = 'en';
|
||||
localStorage.setItem(languageStorageItemKey, englishLanguageCode);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updates data', () => {
|
||||
beforeEach(async () => {
|
||||
await setup(DatabaseConstants.demoStateResume1Id);
|
||||
});
|
||||
|
||||
it('when input value is changed', async () => {
|
||||
const input = screen.getByRole('textbox', { name: /address line 1/i });
|
||||
const newInputValue = 'test street 123';
|
||||
const now = new Date().getTime();
|
||||
|
||||
fireEvent.change(input, { target: { value: newInputValue } });
|
||||
|
||||
expect(input.value).toBe(newInputValue);
|
||||
|
||||
await expectDatabaseUpdateToHaveCompleted();
|
||||
const mockDatabaseUpdateFunctionCallArgument =
|
||||
mockDatabaseUpdateFunction.mock.calls[0][0];
|
||||
expect(mockDatabaseUpdateFunctionCallArgument.id).toBe(resumeId);
|
||||
expect(mockDatabaseUpdateFunctionCallArgument.profile.address.line1).toBe(
|
||||
newInputValue,
|
||||
);
|
||||
expect(
|
||||
mockDatabaseUpdateFunctionCallArgument.updatedAt,
|
||||
).toBeGreaterThanOrEqual(now);
|
||||
});
|
||||
});
|
||||
|
||||
describe('while loading', () => {
|
||||
beforeEach(async () => {
|
||||
await setup(DatabaseConstants.demoStateResume1Id, false, false);
|
||||
});
|
||||
|
||||
it('renders loading screen', async () => {
|
||||
expect(screen.getByTestId(loadingScreenTestId)).toBeInTheDocument();
|
||||
|
||||
await waitForElementToBeRemoved(() =>
|
||||
screen.getByTestId(loadingScreenTestId),
|
||||
);
|
||||
|
||||
await fnWaitForDatabaseUpdateToHaveCompleted();
|
||||
});
|
||||
});
|
||||
|
||||
describe('with resume in initial state', () => {
|
||||
beforeEach(async () => {
|
||||
await setup(DatabaseConstants.initialStateResumeId, false, false);
|
||||
});
|
||||
|
||||
it('displays load demo data notification', async () => {
|
||||
const notification = await screen.findByRole('alert');
|
||||
expect(
|
||||
getByText(
|
||||
notification,
|
||||
/Not sure where to begin\? Try loading demo data/i,
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
fireEvent.click(notification);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,151 @@
|
||||
import {
|
||||
fireEvent,
|
||||
getByText,
|
||||
screen,
|
||||
waitFor,
|
||||
waitForElementToBeRemoved,
|
||||
} from '@testing-library/react';
|
||||
|
||||
import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase';
|
||||
|
||||
import { createResumeButtonDataTestId } from '../../../components/dashboard/CreateResume';
|
||||
import {
|
||||
waitForResumeToBeRenderedInPreview,
|
||||
expectResumeToBeRenderedInPreview,
|
||||
waitForModalWindowToHaveBeenClosed,
|
||||
dismissNotification,
|
||||
unsplashPhotoResponseUrl,
|
||||
setupWithFetchMockAndWait,
|
||||
} from './helpers/dashboard';
|
||||
|
||||
const tooShortResumeName = 'CV 1';
|
||||
const validResumeName = 'Resume for SW development roles';
|
||||
|
||||
async function setup() {
|
||||
const user = DatabaseConstants.user1;
|
||||
await setupWithFetchMockAndWait(user, true);
|
||||
|
||||
const dashboardCreateResumeButton = await screen.findByTestId(
|
||||
createResumeButtonDataTestId,
|
||||
);
|
||||
fireEvent.click(dashboardCreateResumeButton);
|
||||
|
||||
const nameTextBox = screen.getByRole('textbox', { name: /name/i });
|
||||
return { user, nameTextBox };
|
||||
}
|
||||
|
||||
async function setupAndSubmit(resumeName) {
|
||||
const { user, nameTextBox } = await setup();
|
||||
|
||||
fireEvent.change(nameTextBox, {
|
||||
target: { value: resumeName },
|
||||
});
|
||||
|
||||
const modalCreateResumeButton = screen.getByRole('button', {
|
||||
name: /create resume/i,
|
||||
});
|
||||
fireEvent.click(modalCreateResumeButton);
|
||||
|
||||
return { user };
|
||||
}
|
||||
|
||||
describe('with invalid name', () => {
|
||||
it('displays validation error', async () => {
|
||||
const { nameTextBox } = await setup();
|
||||
|
||||
fireEvent.change(nameTextBox, { target: { value: tooShortResumeName } });
|
||||
fireEvent.blur(nameTextBox);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(
|
||||
screen.getByText(/Please enter at least 5 characters/i),
|
||||
).toBeInTheDocument(),
|
||||
);
|
||||
});
|
||||
|
||||
it('displays notification', async () => {
|
||||
await setupAndSubmit(tooShortResumeName);
|
||||
|
||||
const notification = await screen.findByRole('alert');
|
||||
expect(
|
||||
getByText(
|
||||
notification,
|
||||
/You might need to fill up all the required fields/i,
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
dismissNotification(notification);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with valid name', () => {
|
||||
it('renders loading message', async () => {
|
||||
await setupAndSubmit(validResumeName);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(
|
||||
screen.getByRole('button', {
|
||||
name: /loading/i,
|
||||
}),
|
||||
).toBeInTheDocument(),
|
||||
);
|
||||
await waitForElementToBeRemoved(() =>
|
||||
screen.getByRole('button', {
|
||||
name: /loading/i,
|
||||
}),
|
||||
);
|
||||
|
||||
await waitForModalWindowToHaveBeenClosed();
|
||||
await waitForResumeToBeRenderedInPreview(validResumeName);
|
||||
});
|
||||
|
||||
it('closes modal window', async () => {
|
||||
await setupAndSubmit(validResumeName);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(waitForModalWindowToHaveBeenClosed()).resolves.toBeUndefined(),
|
||||
);
|
||||
|
||||
await waitForResumeToBeRenderedInPreview(validResumeName);
|
||||
});
|
||||
|
||||
it('renders created resume in preview', async () => {
|
||||
await setupAndSubmit(validResumeName);
|
||||
|
||||
await waitForModalWindowToHaveBeenClosed();
|
||||
|
||||
await waitFor(() =>
|
||||
expect(
|
||||
expectResumeToBeRenderedInPreview(validResumeName),
|
||||
).resolves.toBeUndefined(),
|
||||
);
|
||||
});
|
||||
|
||||
it('adds resume in initial state to database', async () => {
|
||||
const now = new Date().getTime();
|
||||
const { user } = await setupAndSubmit(validResumeName);
|
||||
|
||||
await waitForModalWindowToHaveBeenClosed();
|
||||
await waitForResumeToBeRenderedInPreview(validResumeName);
|
||||
|
||||
const actualUserResumes = (
|
||||
await FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo(user.uid)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(Object.values(actualUserResumes)).toHaveLength(3);
|
||||
|
||||
const actualUserResumesFiltered = Object.values(actualUserResumes).filter(
|
||||
(resume) => resume.name === validResumeName,
|
||||
);
|
||||
expect(actualUserResumesFiltered).toHaveLength(1);
|
||||
const createdResume = actualUserResumesFiltered[0];
|
||||
expect(createdResume.id).toBeTruthy();
|
||||
expect(createdResume.preview).toBeTruthy();
|
||||
expect(createdResume.preview).toEqual(unsplashPhotoResponseUrl);
|
||||
expect(createdResume.createdAt).toBeTruthy();
|
||||
expect(createdResume.createdAt).toBeGreaterThanOrEqual(now);
|
||||
expect(createdResume.createdAt).toEqual(createdResume.updatedAt);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,119 @@
|
||||
import {
|
||||
fireEvent,
|
||||
getByText,
|
||||
queryByText,
|
||||
screen,
|
||||
waitFor,
|
||||
} from '@testing-library/react';
|
||||
|
||||
import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase';
|
||||
|
||||
import { menuToggleDataTestIdPrefix as resumePreviewMenuToggleDataTestIdPrefix } from '../../../components/dashboard/ResumePreview';
|
||||
import {
|
||||
setupAndWait,
|
||||
waitForResumeToDisappearFromPreview,
|
||||
expectResumeToBeRenderedInPreview,
|
||||
dismissNotification,
|
||||
findAndDismissNotification,
|
||||
} from './helpers/dashboard';
|
||||
|
||||
const waitForDatabaseRemoveToHaveCompleted = async (
|
||||
mockDatabaseRemoveFunction,
|
||||
) => {
|
||||
await waitFor(() => mockDatabaseRemoveFunction.mock.results[0].value);
|
||||
};
|
||||
|
||||
const expectDatabaseRemoveToHaveCompleted = async (
|
||||
mockDatabaseRemoveFunction,
|
||||
) => {
|
||||
await waitFor(() =>
|
||||
expect(mockDatabaseRemoveFunction).toHaveBeenCalledTimes(1),
|
||||
);
|
||||
await waitFor(() =>
|
||||
expect(
|
||||
mockDatabaseRemoveFunction.mock.results[0].value,
|
||||
).resolves.toBeUndefined(),
|
||||
);
|
||||
};
|
||||
|
||||
async function setup() {
|
||||
const userResumes = await setupAndWait(DatabaseConstants.user1, true);
|
||||
|
||||
const [resumeToDelete] = Object.values(userResumes).filter(
|
||||
(resume) => resume.id === DatabaseConstants.demoStateResume1Id,
|
||||
);
|
||||
const resumeToDeleteId = resumeToDelete.id;
|
||||
const [undeletedResume] = Object.values(userResumes).filter(
|
||||
(resume) => resume.id === DatabaseConstants.initialStateResumeId,
|
||||
);
|
||||
|
||||
const mockDatabaseRemoveFunction = jest.spyOn(
|
||||
FirebaseStub.database().ref(
|
||||
`${DatabaseConstants.resumesPath}/${resumeToDeleteId}`,
|
||||
),
|
||||
'remove',
|
||||
);
|
||||
|
||||
const resumeToDeleteMenuToggle = await screen.findByTestId(
|
||||
`${resumePreviewMenuToggleDataTestIdPrefix}${resumeToDeleteId}`,
|
||||
);
|
||||
fireEvent.click(resumeToDeleteMenuToggle);
|
||||
|
||||
const menuItems = screen.getAllByRole('menuitem');
|
||||
let deleteMenuItem = null;
|
||||
for (let index = 0; index < menuItems.length; index++) {
|
||||
if (queryByText(menuItems[index], /delete/i)) {
|
||||
deleteMenuItem = menuItems[index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
fireEvent.click(deleteMenuItem);
|
||||
|
||||
return { resumeToDelete, undeletedResume, mockDatabaseRemoveFunction };
|
||||
}
|
||||
|
||||
it('removes resume from database and preview', async () => {
|
||||
const {
|
||||
resumeToDelete,
|
||||
undeletedResume,
|
||||
mockDatabaseRemoveFunction,
|
||||
} = await setup();
|
||||
|
||||
await findAndDismissNotification();
|
||||
|
||||
await expectDatabaseRemoveToHaveCompleted(mockDatabaseRemoveFunction);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(
|
||||
waitForResumeToDisappearFromPreview(resumeToDelete.name),
|
||||
).resolves.toBeUndefined(),
|
||||
);
|
||||
await expectResumeToBeRenderedInPreview(undeletedResume.name);
|
||||
});
|
||||
|
||||
it('displays notification', async () => {
|
||||
const { resumeToDelete, mockDatabaseRemoveFunction } = await setup();
|
||||
|
||||
const notification = await screen.findByRole('alert');
|
||||
expect(
|
||||
getByText(
|
||||
notification,
|
||||
new RegExp(`${resumeToDelete.name} was deleted successfully`, 'i'),
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
dismissNotification(notification);
|
||||
|
||||
await waitForDatabaseRemoveToHaveCompleted(mockDatabaseRemoveFunction);
|
||||
await waitForResumeToDisappearFromPreview(resumeToDelete.name);
|
||||
});
|
||||
|
||||
it('closes menu', async () => {
|
||||
const { resumeToDelete, mockDatabaseRemoveFunction } = await setup();
|
||||
|
||||
const menuItems = screen.queryAllByRole('menuitem');
|
||||
expect(menuItems).toHaveLength(0);
|
||||
|
||||
await findAndDismissNotification();
|
||||
await waitForDatabaseRemoveToHaveCompleted(mockDatabaseRemoveFunction);
|
||||
await waitForResumeToDisappearFromPreview(resumeToDelete.name);
|
||||
});
|
||||
@@ -0,0 +1,101 @@
|
||||
import {
|
||||
fireEvent,
|
||||
queryByText,
|
||||
screen,
|
||||
waitFor,
|
||||
} from '@testing-library/react';
|
||||
|
||||
import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase';
|
||||
|
||||
import { menuToggleDataTestIdPrefix as resumePreviewMenuToggleDataTestIdPrefix } from '../../../components/dashboard/ResumePreview';
|
||||
import {
|
||||
setupWithFetchMockAndWait,
|
||||
waitForResumeToBeRenderedInPreview,
|
||||
expectResumeToBeRenderedInPreview,
|
||||
unsplashPhotoResponseUrl,
|
||||
} from './helpers/dashboard';
|
||||
|
||||
async function setup() {
|
||||
const user = DatabaseConstants.user1;
|
||||
const userResumes = await setupWithFetchMockAndWait(user, true);
|
||||
|
||||
const [resumeToDuplicate] = Object.values(userResumes).filter(
|
||||
(resume) => resume.id === DatabaseConstants.demoStateResume1Id,
|
||||
);
|
||||
const resumeToDuplicateId = resumeToDuplicate.id;
|
||||
const duplicateResumeName = `${resumeToDuplicate.name} Copy`;
|
||||
|
||||
const resumeToDuplicateMenuToggle = await screen.findByTestId(
|
||||
`${resumePreviewMenuToggleDataTestIdPrefix}${resumeToDuplicateId}`,
|
||||
);
|
||||
fireEvent.click(resumeToDuplicateMenuToggle);
|
||||
|
||||
const menuItems = screen.getAllByRole('menuitem');
|
||||
let duplicateMenuItem = null;
|
||||
for (let index = 0; index < menuItems.length; index++) {
|
||||
if (queryByText(menuItems[index], /duplicate/i)) {
|
||||
duplicateMenuItem = menuItems[index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
fireEvent.click(duplicateMenuItem);
|
||||
|
||||
return { user, resumeToDuplicate, duplicateResumeName };
|
||||
}
|
||||
|
||||
it('renders duplicate resume in preview', async () => {
|
||||
const { duplicateResumeName } = await setup();
|
||||
|
||||
await waitFor(() =>
|
||||
expect(
|
||||
expectResumeToBeRenderedInPreview(duplicateResumeName),
|
||||
).resolves.toBeUndefined(),
|
||||
);
|
||||
});
|
||||
|
||||
it('adds duplicate resume to database', async () => {
|
||||
const now = new Date().getTime();
|
||||
const { user, resumeToDuplicate, duplicateResumeName } = await setup();
|
||||
|
||||
await waitForResumeToBeRenderedInPreview(duplicateResumeName);
|
||||
|
||||
const actualUserResumes = (
|
||||
await FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo(user.uid)
|
||||
.once('value')
|
||||
).val();
|
||||
expect(Object.values(actualUserResumes)).toHaveLength(3);
|
||||
|
||||
const actualUserResumesFiltered = Object.values(actualUserResumes).filter(
|
||||
(resume) =>
|
||||
resume.name === duplicateResumeName && resume.id !== resumeToDuplicate.id,
|
||||
);
|
||||
expect(actualUserResumesFiltered).toHaveLength(1);
|
||||
const createdResume = actualUserResumesFiltered[0];
|
||||
expect(createdResume.id).toBeTruthy();
|
||||
expect(createdResume.preview).toBeTruthy();
|
||||
expect(createdResume.preview).toEqual(unsplashPhotoResponseUrl);
|
||||
expect(createdResume.createdAt).toBeTruthy();
|
||||
expect(createdResume.createdAt).toBeGreaterThanOrEqual(now);
|
||||
expect(createdResume.createdAt).toEqual(createdResume.updatedAt);
|
||||
const expectedResume = {
|
||||
...resumeToDuplicate,
|
||||
id: createdResume.id,
|
||||
name: createdResume.name,
|
||||
preview: createdResume.preview,
|
||||
createdAt: createdResume.createdAt,
|
||||
updatedAt: createdResume.updatedAt,
|
||||
};
|
||||
expect(createdResume).toEqual(expectedResume);
|
||||
});
|
||||
|
||||
it('closes menu', async () => {
|
||||
const { duplicateResumeName } = await setup();
|
||||
|
||||
const menuItems = screen.queryAllByRole('menuitem');
|
||||
expect(menuItems).toHaveLength(0);
|
||||
|
||||
await waitForResumeToBeRenderedInPreview(duplicateResumeName);
|
||||
});
|
||||
@@ -0,0 +1,50 @@
|
||||
import { screen, waitFor } from '@testing-library/react';
|
||||
|
||||
import { DatabaseConstants } from 'gatsby-plugin-firebase';
|
||||
|
||||
import { createResumeButtonDataTestId } from '../../../components/dashboard/CreateResume';
|
||||
import setup, {
|
||||
setupAndWait,
|
||||
expectResumeToBeRenderedInPreview,
|
||||
expectLoadingScreenToBeRendered,
|
||||
waitForLoadingScreenToDisappear,
|
||||
} from './helpers/dashboard';
|
||||
|
||||
const user = DatabaseConstants.user1;
|
||||
|
||||
it('renders loading screen', async () => {
|
||||
await setup(user);
|
||||
|
||||
expect(expectLoadingScreenToBeRendered()).toBeUndefined();
|
||||
await waitForLoadingScreenToDisappear();
|
||||
});
|
||||
|
||||
it('renders document title', async () => {
|
||||
await setupAndWait(user, true);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(document.title).toEqual('Dashboard | Reactive Resume');
|
||||
});
|
||||
});
|
||||
|
||||
it('renders create resume', async () => {
|
||||
await setupAndWait(user, true);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(/create resume/i)).toBeInTheDocument();
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
screen.getByTestId(createResumeButtonDataTestId),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders preview of user resumes', async () => {
|
||||
const userResumes = await setupAndWait(user, true);
|
||||
|
||||
expect(Object.keys(userResumes)).toHaveLength(2);
|
||||
|
||||
await expectResumeToBeRenderedInPreview(Object.values(userResumes)[0].name);
|
||||
await expectResumeToBeRenderedInPreview(Object.values(userResumes)[1].name);
|
||||
});
|
||||
@@ -1,200 +0,0 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
fireEvent,
|
||||
getByText,
|
||||
queryByText,
|
||||
render,
|
||||
screen,
|
||||
waitFor,
|
||||
waitForElementToBeRemoved,
|
||||
} from '@testing-library/react';
|
||||
|
||||
import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase';
|
||||
|
||||
import '../../../i18n/index';
|
||||
import '../../../utils/dayjs';
|
||||
import { dataTestId as loadingScreenTestId } from '../../../components/router/LoadingScreen';
|
||||
import { menuToggleDataTestIdPrefix as resumePreviewMenuToggleDataTestIdPrefix } from '../../../components/dashboard/ResumePreview';
|
||||
import { SettingsProvider } from '../../../contexts/SettingsContext';
|
||||
import { ModalProvider } from '../../../contexts/ModalContext';
|
||||
import { UserProvider } from '../../../contexts/UserContext';
|
||||
import { DatabaseProvider } from '../../../contexts/DatabaseContext';
|
||||
import { ResumeProvider } from '../../../contexts/ResumeContext';
|
||||
import { StorageProvider } from '../../../contexts/StorageContext';
|
||||
import Wrapper from '../../../components/shared/Wrapper';
|
||||
import Dashboard from '../dashboard';
|
||||
|
||||
describe('Dashboard', () => {
|
||||
let userResumes = null;
|
||||
const user = DatabaseConstants.user1;
|
||||
|
||||
const waitForResumeToBeRenderedInPreview = async (resume) => {
|
||||
await screen.findByText(resume.name);
|
||||
};
|
||||
|
||||
const expectResumeToBeRenderedInPreview = async (resume) => {
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(resume.name)).toBeInTheDocument();
|
||||
});
|
||||
};
|
||||
|
||||
async function setup(waitForLoadingScreenToDisappear = true) {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
userResumes = (
|
||||
await FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo(user.uid)
|
||||
.once('value')
|
||||
).val();
|
||||
|
||||
FirebaseStub.auth().signInAnonymously();
|
||||
|
||||
render(
|
||||
<SettingsProvider>
|
||||
<ModalProvider>
|
||||
<UserProvider>
|
||||
<DatabaseProvider>
|
||||
<ResumeProvider>
|
||||
<StorageProvider>
|
||||
<Wrapper>
|
||||
<Dashboard user={user} />
|
||||
</Wrapper>
|
||||
</StorageProvider>
|
||||
</ResumeProvider>
|
||||
</DatabaseProvider>
|
||||
</UserProvider>
|
||||
</ModalProvider>
|
||||
</SettingsProvider>,
|
||||
);
|
||||
|
||||
if (waitForLoadingScreenToDisappear) {
|
||||
await waitForElementToBeRemoved(() =>
|
||||
screen.getByTestId(loadingScreenTestId),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
describe('renders', () => {
|
||||
beforeEach(async () => {
|
||||
await setup();
|
||||
});
|
||||
|
||||
it('document title', async () => {
|
||||
await waitFor(() => {
|
||||
expect(document.title).toEqual('Dashboard | Reactive Resume');
|
||||
});
|
||||
});
|
||||
|
||||
it('create resume', async () => {
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(/create resume/i)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('preview of user resumes', async () => {
|
||||
expect(Object.keys(userResumes)).toHaveLength(2);
|
||||
|
||||
await expectResumeToBeRenderedInPreview(Object.values(userResumes)[0]);
|
||||
await expectResumeToBeRenderedInPreview(Object.values(userResumes)[1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when resume is deleted', () => {
|
||||
let mockDatabaseRemoveFunction = null;
|
||||
let resumeToDelete = null;
|
||||
let undeletedResume = null;
|
||||
let resumeToDeleteId = null;
|
||||
|
||||
const waitForDatabaseRemoveToHaveCompleted = async () => {
|
||||
await waitFor(() => mockDatabaseRemoveFunction.mock.results[0].value);
|
||||
};
|
||||
|
||||
const expectDatabaseRemoveToHaveCompleted = async () => {
|
||||
await waitFor(() =>
|
||||
expect(mockDatabaseRemoveFunction).toHaveBeenCalledTimes(1),
|
||||
);
|
||||
await waitFor(() =>
|
||||
expect(
|
||||
mockDatabaseRemoveFunction.mock.results[0].value,
|
||||
).resolves.toBeUndefined(),
|
||||
);
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
await setup();
|
||||
|
||||
[resumeToDelete, undeletedResume] = Object.values(userResumes);
|
||||
resumeToDeleteId = resumeToDelete.id;
|
||||
|
||||
mockDatabaseRemoveFunction = jest.spyOn(
|
||||
FirebaseStub.database().ref(
|
||||
`${DatabaseConstants.resumesPath}/${resumeToDeleteId}`,
|
||||
),
|
||||
'remove',
|
||||
);
|
||||
|
||||
const resumeToDeleteMenuToggle = await screen.findByTestId(
|
||||
`${resumePreviewMenuToggleDataTestIdPrefix}${resumeToDeleteId}`,
|
||||
);
|
||||
fireEvent.click(resumeToDeleteMenuToggle);
|
||||
|
||||
const menuItems = screen.getAllByRole('menuitem');
|
||||
let deleteMenuItem = null;
|
||||
for (let index = 0; index < menuItems.length; index++) {
|
||||
if (queryByText(menuItems[index], /delete/i)) {
|
||||
deleteMenuItem = menuItems[index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
fireEvent.click(deleteMenuItem);
|
||||
});
|
||||
|
||||
it('removes it from database and preview', async () => {
|
||||
await expectDatabaseRemoveToHaveCompleted();
|
||||
|
||||
await waitFor(() =>
|
||||
expect(screen.queryByText(resumeToDelete.name)).toBeNull(),
|
||||
);
|
||||
await expectResumeToBeRenderedInPreview(undeletedResume);
|
||||
});
|
||||
|
||||
it('displays notification', async () => {
|
||||
const notification = await screen.findByRole('alert');
|
||||
expect(
|
||||
getByText(
|
||||
notification,
|
||||
new RegExp(`${resumeToDelete.name} was deleted successfully`, 'i'),
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
fireEvent.click(notification);
|
||||
|
||||
await waitForDatabaseRemoveToHaveCompleted();
|
||||
});
|
||||
|
||||
it('closes menu', async () => {
|
||||
const menuItems = screen.queryAllByRole('menuitem');
|
||||
expect(menuItems).toHaveLength(0);
|
||||
|
||||
await waitForDatabaseRemoveToHaveCompleted();
|
||||
});
|
||||
});
|
||||
|
||||
describe('while loading', () => {
|
||||
beforeEach(async () => {
|
||||
await setup(false);
|
||||
});
|
||||
|
||||
it('renders loading screen', async () => {
|
||||
expect(screen.getByTestId(loadingScreenTestId)).toBeInTheDocument();
|
||||
|
||||
await waitForElementToBeRemoved(() =>
|
||||
screen.getByTestId(loadingScreenTestId),
|
||||
);
|
||||
|
||||
await waitForResumeToBeRenderedInPreview(Object.values(userResumes)[0]);
|
||||
await waitForResumeToBeRenderedInPreview(Object.values(userResumes)[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,127 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
render,
|
||||
screen,
|
||||
waitFor,
|
||||
waitForElementToBeRemoved,
|
||||
} from '@testing-library/react';
|
||||
|
||||
import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase';
|
||||
|
||||
import { dataTestId as loadingScreenTestId } from '../../../../components/router/LoadingScreen';
|
||||
import { SettingsProvider } from '../../../../contexts/SettingsContext';
|
||||
import { ModalProvider } from '../../../../contexts/ModalContext';
|
||||
import { UserProvider } from '../../../../contexts/UserContext';
|
||||
import {
|
||||
DatabaseProvider,
|
||||
DebounceWaitTime,
|
||||
} from '../../../../contexts/DatabaseContext';
|
||||
import { ResumeProvider } from '../../../../contexts/ResumeContext';
|
||||
import { StorageProvider } from '../../../../contexts/StorageContext';
|
||||
import Wrapper from '../../../../components/shared/Wrapper';
|
||||
import Builder from '../../builder';
|
||||
|
||||
const waitForDatabaseUpdateToHaveCompletedFn = async (
|
||||
mockDatabaseUpdateFunction,
|
||||
) => {
|
||||
await waitFor(() => mockDatabaseUpdateFunction.mock.calls[0][0], {
|
||||
timeout: DebounceWaitTime,
|
||||
});
|
||||
await waitFor(() => mockDatabaseUpdateFunction.mock.results[0].value);
|
||||
};
|
||||
|
||||
const expectDatabaseUpdateToHaveCompleted = async (
|
||||
mockDatabaseUpdateFunction,
|
||||
) => {
|
||||
await waitFor(
|
||||
() => expect(mockDatabaseUpdateFunction).toHaveBeenCalledTimes(1),
|
||||
{
|
||||
timeout: DebounceWaitTime,
|
||||
},
|
||||
);
|
||||
await waitFor(() =>
|
||||
expect(
|
||||
mockDatabaseUpdateFunction.mock.results[0].value,
|
||||
).resolves.toBeUndefined(),
|
||||
);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
async function _setup(
|
||||
resumeId,
|
||||
waitForLoadingScreenToDisappear,
|
||||
waitForDatabaseUpdateToHaveCompleted,
|
||||
) {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
const resume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.once('value')
|
||||
).val();
|
||||
|
||||
const mockDatabaseUpdateFunction = jest.spyOn(
|
||||
FirebaseStub.database().ref(`${DatabaseConstants.resumesPath}/${resumeId}`),
|
||||
'update',
|
||||
);
|
||||
|
||||
FirebaseStub.auth().signInAnonymously();
|
||||
|
||||
render(
|
||||
<SettingsProvider>
|
||||
<ModalProvider>
|
||||
<UserProvider>
|
||||
<DatabaseProvider>
|
||||
<ResumeProvider>
|
||||
<StorageProvider>
|
||||
<Wrapper>
|
||||
<Builder id={resumeId} />
|
||||
</Wrapper>
|
||||
</StorageProvider>
|
||||
</ResumeProvider>
|
||||
</DatabaseProvider>
|
||||
</UserProvider>
|
||||
</ModalProvider>
|
||||
</SettingsProvider>,
|
||||
);
|
||||
|
||||
if (waitForLoadingScreenToDisappear) {
|
||||
await waitForElementToBeRemoved(() =>
|
||||
screen.getByTestId(loadingScreenTestId),
|
||||
);
|
||||
}
|
||||
|
||||
if (waitForDatabaseUpdateToHaveCompleted) {
|
||||
await waitForDatabaseUpdateToHaveCompletedFn(mockDatabaseUpdateFunction);
|
||||
}
|
||||
|
||||
mockDatabaseUpdateFunction.mockClear();
|
||||
|
||||
return { resume, mockDatabaseUpdateFunction };
|
||||
}
|
||||
|
||||
async function setup(resumeId) {
|
||||
const returnValue = await _setup(resumeId, false, false);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
async function setupAndWait(
|
||||
resumeId,
|
||||
waitForLoadingScreenToDisappear,
|
||||
waitForDatabaseUpdateToHaveCompleted,
|
||||
) {
|
||||
const returnValue = await _setup(
|
||||
resumeId,
|
||||
waitForLoadingScreenToDisappear,
|
||||
waitForDatabaseUpdateToHaveCompleted,
|
||||
);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
export default setup;
|
||||
|
||||
export {
|
||||
setupAndWait,
|
||||
waitForDatabaseUpdateToHaveCompletedFn as waitForDatabaseUpdateToHaveCompleted,
|
||||
expectDatabaseUpdateToHaveCompleted,
|
||||
};
|
||||
@@ -0,0 +1,167 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
fireEvent,
|
||||
render,
|
||||
screen,
|
||||
waitFor,
|
||||
waitForElementToBeRemoved,
|
||||
} from '@testing-library/react';
|
||||
|
||||
import fetchMock from 'jest-fetch-mock';
|
||||
|
||||
import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase';
|
||||
|
||||
import '../../../../i18n/index';
|
||||
import '../../../../utils/dayjs';
|
||||
import { dataTestId as loadingScreenTestId } from '../../../../components/router/LoadingScreen';
|
||||
import { unsplashPhotoRequestUrl, delay } from '../../../../utils/index';
|
||||
import { SettingsProvider } from '../../../../contexts/SettingsContext';
|
||||
import { ModalProvider } from '../../../../contexts/ModalContext';
|
||||
import { UserProvider } from '../../../../contexts/UserContext';
|
||||
import { DatabaseProvider } from '../../../../contexts/DatabaseContext';
|
||||
import { ResumeProvider } from '../../../../contexts/ResumeContext';
|
||||
import { StorageProvider } from '../../../../contexts/StorageContext';
|
||||
import Wrapper from '../../../../components/shared/Wrapper';
|
||||
import Dashboard from '../../dashboard';
|
||||
|
||||
const waitForResumeToBeRenderedInPreview = async (resumeName) => {
|
||||
await screen.findByText(resumeName);
|
||||
};
|
||||
|
||||
const waitForResumeToDisappearFromPreview = async (resumeName) => {
|
||||
await waitFor(() =>
|
||||
screen.queryByText(resumeName) ? Promise.reject() : Promise.resolve(),
|
||||
);
|
||||
};
|
||||
|
||||
const expectResumeToBeRenderedInPreview = async (resumeName) => {
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(resumeName)).toBeInTheDocument();
|
||||
});
|
||||
};
|
||||
|
||||
const waitForModalWindowToHaveBeenClosed = async () => {
|
||||
await waitFor(() =>
|
||||
screen.queryByRole('textbox', { name: /name/i })
|
||||
? Promise.reject()
|
||||
: Promise.resolve(),
|
||||
);
|
||||
};
|
||||
|
||||
const dismissNotification = (notification) => {
|
||||
fireEvent.click(notification);
|
||||
};
|
||||
|
||||
const findAndDismissNotification = async () => {
|
||||
const notification = await screen.findByRole('alert');
|
||||
dismissNotification(notification);
|
||||
};
|
||||
|
||||
const expectLoadingScreenToBeRendered = () => {
|
||||
expect(screen.getByTestId(loadingScreenTestId)).toBeInTheDocument();
|
||||
};
|
||||
|
||||
const waitForLoadingScreenToDisappearFn = async () => {
|
||||
await waitForElementToBeRemoved(() =>
|
||||
screen.getByTestId(loadingScreenTestId),
|
||||
);
|
||||
};
|
||||
|
||||
const unsplashPhotoResponseUrl = 'https://test-url-123456789.com';
|
||||
|
||||
const setupFetchMockFn = () => {
|
||||
fetchMock.resetMocks();
|
||||
|
||||
fetchMock.mockImplementationOnce(async (input) => {
|
||||
await delay(100);
|
||||
|
||||
if (input === unsplashPhotoRequestUrl) {
|
||||
return {
|
||||
url: unsplashPhotoResponseUrl,
|
||||
};
|
||||
}
|
||||
|
||||
throw new Error('Unsupported input.');
|
||||
});
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
async function _setup(user, waitForLoadingScreenToDisappear, setupFetchMock) {
|
||||
if (setupFetchMock) {
|
||||
setupFetchMockFn();
|
||||
}
|
||||
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
const userResumes = (
|
||||
await FirebaseStub.database()
|
||||
.ref(DatabaseConstants.resumesPath)
|
||||
.orderByChild('user')
|
||||
.equalTo(user.uid)
|
||||
.once('value')
|
||||
).val();
|
||||
|
||||
FirebaseStub.auth().signInAnonymously();
|
||||
|
||||
render(
|
||||
<SettingsProvider>
|
||||
<ModalProvider>
|
||||
<UserProvider>
|
||||
<DatabaseProvider>
|
||||
<ResumeProvider>
|
||||
<StorageProvider>
|
||||
<Wrapper>
|
||||
<Dashboard user={user} />
|
||||
</Wrapper>
|
||||
</StorageProvider>
|
||||
</ResumeProvider>
|
||||
</DatabaseProvider>
|
||||
</UserProvider>
|
||||
</ModalProvider>
|
||||
</SettingsProvider>,
|
||||
);
|
||||
|
||||
if (waitForLoadingScreenToDisappear) {
|
||||
await waitForLoadingScreenToDisappearFn();
|
||||
}
|
||||
|
||||
return userResumes;
|
||||
}
|
||||
|
||||
async function setup(user) {
|
||||
const userResumes = await _setup(user, false, false);
|
||||
return userResumes;
|
||||
}
|
||||
|
||||
async function setupAndWait(user, waitForLoadingScreenToDisappear) {
|
||||
const userResumes = await _setup(
|
||||
user,
|
||||
waitForLoadingScreenToDisappear,
|
||||
false,
|
||||
);
|
||||
return userResumes;
|
||||
}
|
||||
|
||||
async function setupWithFetchMockAndWait(
|
||||
user,
|
||||
waitForLoadingScreenToDisappear,
|
||||
) {
|
||||
const userResumes = await _setup(user, waitForLoadingScreenToDisappear, true);
|
||||
return userResumes;
|
||||
}
|
||||
|
||||
export default setup;
|
||||
|
||||
export {
|
||||
setupAndWait,
|
||||
setupWithFetchMockAndWait,
|
||||
waitForResumeToBeRenderedInPreview,
|
||||
waitForResumeToDisappearFromPreview,
|
||||
expectResumeToBeRenderedInPreview,
|
||||
waitForModalWindowToHaveBeenClosed,
|
||||
dismissNotification,
|
||||
findAndDismissNotification,
|
||||
expectLoadingScreenToBeRendered,
|
||||
waitForLoadingScreenToDisappearFn as waitForLoadingScreenToDisappear,
|
||||
unsplashPhotoResponseUrl,
|
||||
};
|
||||
@@ -6,47 +6,48 @@ import FirebaseStub, { DatabaseConstants } from 'gatsby-plugin-firebase';
|
||||
import '../../i18n/index';
|
||||
import Castform from '../Castform';
|
||||
|
||||
describe('Castform', () => {
|
||||
let resume = {};
|
||||
const birthDateLabelMatcher = /Date of birth/i;
|
||||
|
||||
beforeEach(async () => {
|
||||
FirebaseStub.database().initializeData();
|
||||
async function setup(resumeId) {
|
||||
FirebaseStub.database().initializeData();
|
||||
|
||||
const resumeId = DatabaseConstants.initialStateResumeId;
|
||||
resume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.once('value')
|
||||
).val();
|
||||
});
|
||||
const resume = (
|
||||
await FirebaseStub.database()
|
||||
.ref(`${DatabaseConstants.resumesPath}/${resumeId}`)
|
||||
.once('value')
|
||||
).val();
|
||||
|
||||
it('renders correctly', () => {
|
||||
const { container } = render(<Castform data={resume} />);
|
||||
return resume;
|
||||
}
|
||||
|
||||
expect(container).toBeTruthy();
|
||||
expect(container).toBeInTheDocument();
|
||||
});
|
||||
test('renders correctly', async () => {
|
||||
const resume = await setup(DatabaseConstants.initialStateResumeId);
|
||||
|
||||
describe('date of birth', () => {
|
||||
const birthDateLabelMatcher = /Date of birth/i;
|
||||
const { container } = render(<Castform data={resume} />);
|
||||
|
||||
it('is not shown if not provided', () => {
|
||||
render(<Castform data={resume} />);
|
||||
|
||||
expect(screen.queryByText(birthDateLabelMatcher)).toBeNull();
|
||||
});
|
||||
|
||||
it('is shown if provided', () => {
|
||||
const birthDate = new Date(1990, 0, 20);
|
||||
const birthDateFormatted = '20 January 1990';
|
||||
resume.profile.birthDate = birthDate;
|
||||
|
||||
render(<Castform data={resume} />);
|
||||
|
||||
expect(screen.getByText(birthDateLabelMatcher)).toBeTruthy();
|
||||
expect(screen.getByText(birthDateLabelMatcher)).toBeInTheDocument();
|
||||
expect(screen.getByText(birthDateFormatted)).toBeTruthy();
|
||||
expect(screen.getByText(birthDateFormatted)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
expect(container).toBeTruthy();
|
||||
expect(container).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('date of birth is not shown if not provided', async () => {
|
||||
const resume = await setup(DatabaseConstants.initialStateResumeId);
|
||||
|
||||
render(<Castform data={resume} />);
|
||||
|
||||
expect(screen.queryByText(birthDateLabelMatcher)).toBeNull();
|
||||
});
|
||||
|
||||
test('date of birth is shown if provided', async () => {
|
||||
const resume = await setup(DatabaseConstants.initialStateResumeId);
|
||||
|
||||
const birthDate = new Date(1990, 0, 20);
|
||||
const birthDateFormatted = '20 January 1990';
|
||||
resume.profile.birthDate = birthDate;
|
||||
|
||||
render(<Castform data={resume} />);
|
||||
|
||||
expect(screen.getByText(birthDateLabelMatcher)).toBeTruthy();
|
||||
expect(screen.getByText(birthDateLabelMatcher)).toBeInTheDocument();
|
||||
expect(screen.getByText(birthDateFormatted)).toBeTruthy();
|
||||
expect(screen.getByText(birthDateFormatted)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
+8
-1
@@ -54,8 +54,11 @@ export const getFieldProps = (formik, schema, name) => ({
|
||||
...formik.getFieldProps(name),
|
||||
});
|
||||
|
||||
export const unsplashPhotoRequestUrl =
|
||||
'https://source.unsplash.com/featured/400x600';
|
||||
|
||||
export const getUnsplashPhoto = async () => {
|
||||
const response = await fetch('https://source.unsplash.com/featured/400x600');
|
||||
const response = await fetch(unsplashPhotoRequestUrl);
|
||||
return response.url;
|
||||
};
|
||||
|
||||
@@ -121,3 +124,7 @@ export const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => {
|
||||
const blob = new Blob(byteArrays, { type: contentType });
|
||||
return blob;
|
||||
};
|
||||
|
||||
export const delay = async (milliseconds) => {
|
||||
await new Promise((resolve) => setTimeout(resolve, milliseconds));
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user