Skip to content

Commit

Permalink
Basic GitGraph visualization (#292)
Browse files Browse the repository at this point in the history
[Features]
* Initial GitGraph component using react-flow-renderer
* GitGraph components generate commit graphs for repositories
* Graph layout optimizer using dagre.js

[Bugfixes]
* Migrate from .toBe to .toHaveValue in Browser component tests
* Additional React documentation links for useMemo and useState hooks
* Migrate .toBeNull to .not.toBeInTheDocument in CardComponent tests
* Migrate .toBe to .toHaveValue in Editor component tests
* Updated singlequotes for DiffPickerDialog tests
* Migrate .toHaveLength to .toBeInDocument in Explorer component tests
* Migrate .toBeNull to .not.toBeInTheDocument in NewCardButton tests
* Remove .not.toBeNull in favor of .toBeInTheDocument in NewCardDialog component tests
* Minor formatting fixes for style.css and useStyles hook in CardComponent
* Fixed max-len for comments in reduxStoreMock.old.ts
* Updated singlequotes for errorReducer tests
* Disable max-len and singlequote ESLint rules for git.oldspec.ts
* Disable max-len and no-commented-out-tests ESLint rules for git.spec.ts
* Updated singlequotes for pako.oldspec.ts
* Updated singlequotes for io.spec.ts
* Multiple fixes for singlequotes and max-len violations per ESLint
  • Loading branch information
nelsonni authored Jan 20, 2021
1 parent 0a9bf84 commit 38869a4
Show file tree
Hide file tree
Showing 41 changed files with 745 additions and 258 deletions.
2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ React and Redux:
* [Hooks API Reference](https://reactjs.org/docs/hooks-reference.html)
* [Using the React useContext Hook](https://medium.com/digio-australia/using-the-react-usecontext-hook-9f55461c4eae)
* [Idiomatic Redux: Why use action creators?](https://blog.isquaredsoftware.com/2016/10/idiomatic-redux-why-use-action-creators/)
* [ES6 Map with React.useState](https://medium.com/@jalalazimi/es6-map-with-react-usestate-9175cd7b409b)
* [Understanding the React useMemo Hook](https://www.digitalocean.com/community/tutorials/react-usememo)

Jest Testing:
* [Taking Advantage of Jest Matchers (Part 1)](https://benmccormick.org/2017/08/15/jest-matchers-1/)
Expand Down
238 changes: 119 additions & 119 deletions __test__/Browser.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,126 +10,126 @@ import { mockStore } from './__mocks__/reduxStoreMock';
import { wrapInReduxContext } from './__mocks__/dndReduxMock';

describe('BrowserComponent', () => {
const store = mockStore({
canvas: {
id: v4(),
created: DateTime.fromISO('1991-12-26T08:00:00.000-08:00'),
repos: [],
cards: [],
stacks: []
},
stacks: {},
cards: {},
filetypes: {},
metafiles: {},
repos: {},
errors: {}
});

const BrowserComponentContext = wrapInReduxContext(BrowserComponent, store);

it('BrowserComponent allows the user to enter/edit a URL', async () => {
render(<BrowserComponentContext />);
const textBox = screen.getByRole('textbox') as HTMLInputElement;

expect(textBox.value).toBe("https://epiclab.github.io/");

// Type URL into text box
userEvent.clear(screen.getByRole('textbox'));
await userEvent.type(screen.getByRole('textbox'), 'https://google.com');

// Hit Enter button
fireEvent.keyDown(textBox, { key: 'Enter', keyCode: 13, which: 13 });

expect(textBox.value).toBe("https://google.com");
});

it('BrowserComponent allows the user to navigate backwards and forwards in history', async () => {
render(<BrowserComponentContext />);
const backButton = screen.getAllByRole('button')[0];
const forwardButton = screen.getAllByRole('button')[1];
const textBox = screen.getByRole('textbox') as HTMLInputElement;

expect(textBox.value).toBe("https://epiclab.github.io/");
textBox.focus();

// Type URL into text box
userEvent.clear(screen.getByRole('textbox'));
await userEvent.type(screen.getByRole('textbox'), 'https://google.com');

// Press Enter key
fireEvent.keyDown(textBox, { key: 'Enter', keyCode: 13, which: 13 });
expect(screen.getByRole('textbox')).toHaveValue('https://google.com');

// Go back in history
fireEvent.click(backButton);
expect(textBox.value).toBe("https://epiclab.github.io/");

// Go forward in history
fireEvent.click(forwardButton);
expect(textBox.value).toBe("https://google.com/");
});

it('BrowserComponent does not change the page URL when the refresh button is clicked', async () => {
render(<BrowserComponentContext />);
const textBox = screen.getByRole('textbox') as HTMLInputElement;
const refreshButton = screen.getAllByRole('button')[2];

expect(textBox.value).toBe("https://epiclab.github.io/");
fireEvent.click(refreshButton);
expect(textBox.value).toBe("https://epiclab.github.io/");

textBox.focus();

// Type URL into text box
userEvent.clear(screen.getByRole('textbox'));
await userEvent.type(screen.getByRole('textbox'), 'https://google.com');

// Press Enter key
fireEvent.keyDown(textBox, { key: 'Enter', keyCode: 13, which: 13 });

expect(textBox.value).toBe("https://google.com");
fireEvent.click(refreshButton);
expect(textBox.value).toBe("https://google.com");
});
const store = mockStore({
canvas: {
id: v4(),
created: DateTime.fromISO('1991-12-26T08:00:00.000-08:00'),
repos: [],
cards: [],
stacks: []
},
stacks: {},
cards: {},
filetypes: {},
metafiles: {},
repos: {},
errors: {}
});

const BrowserComponentContext = wrapInReduxContext(BrowserComponent, store);

it('BrowserComponent allows the user to enter/edit a URL', async () => {
render(<BrowserComponentContext />);
const textBox = screen.getByRole('textbox') as HTMLInputElement;

expect(textBox).toHaveValue('https://epiclab.github.io/');

// Type URL into text box
userEvent.clear(screen.getByRole('textbox'));
await userEvent.type(screen.getByRole('textbox'), 'https://google.com');

// Hit Enter button
fireEvent.keyDown(textBox, { key: 'Enter', keyCode: 13, which: 13 });

expect(textBox).toHaveValue('https://google.com');
});

it('BrowserComponent allows the user to navigate backwards and forwards in history', async () => {
render(<BrowserComponentContext />);
const backButton = screen.getAllByRole('button')[0];
const forwardButton = screen.getAllByRole('button')[1];
const textBox = screen.getByRole('textbox') as HTMLInputElement;

expect(textBox).toHaveValue('https://epiclab.github.io/');
textBox.focus();

// Type URL into text box
userEvent.clear(screen.getByRole('textbox'));
await userEvent.type(screen.getByRole('textbox'), 'https://google.com');

// Press Enter key
fireEvent.keyDown(textBox, { key: 'Enter', keyCode: 13, which: 13 });
expect(screen.getByRole('textbox')).toHaveValue('https://google.com');

// Go back in history
fireEvent.click(backButton);
expect(textBox).toHaveValue('https://epiclab.github.io/');

// Go forward in history
fireEvent.click(forwardButton);
expect(textBox).toHaveValue('https://google.com/');
});

it('BrowserComponent does not change the page URL when the refresh button is clicked', async () => {
render(<BrowserComponentContext />);
const textBox = screen.getByRole('textbox') as HTMLInputElement;
const refreshButton = screen.getAllByRole('button')[2];

expect(textBox).toHaveValue('https://epiclab.github.io/');
fireEvent.click(refreshButton);
expect(textBox).toHaveValue('https://epiclab.github.io/');

textBox.focus();

// Type URL into text box
userEvent.clear(screen.getByRole('textbox'));
await userEvent.type(screen.getByRole('textbox'), 'https://google.com');

// Press Enter key
fireEvent.keyDown(textBox, { key: 'Enter', keyCode: 13, which: 13 });

expect(textBox).toHaveValue('https://google.com');
fireEvent.click(refreshButton);
expect(textBox).toHaveValue('https://google.com');
});
});

describe('BrowserButton', () => {
const store = mockStore({
canvas: {
id: v4(),
created: DateTime.fromISO('1991-12-26T08:00:00.000-08:00'),
repos: [],
cards: [],
stacks: []
},
stacks: {},
cards: {},
filetypes: {},
metafiles: {
199: {
id: '199',
name: 'Browser',
handler: 'Browser',
modified: DateTime.fromISO('2019-11-19T19:19:47.572-08:00')
},
},
repos: {},
errors: {}
});

const BrowserButtonContext = wrapInReduxContext(BrowserButton, store);

it('BrowserButton calls onClick when clicked', () => {
const onClick = jest.fn();
render(<BrowserButtonContext />);

const button = screen.getByRole('button');
if (button) {
button.addEventListener('click', onClick);
fireEvent.click(button);
}

expect(onClick).toHaveBeenCalled();
});
const store = mockStore({
canvas: {
id: v4(),
created: DateTime.fromISO('1991-12-26T08:00:00.000-08:00'),
repos: [],
cards: [],
stacks: []
},
stacks: {},
cards: {},
filetypes: {},
metafiles: {
199: {
id: '199',
name: 'Browser',
handler: 'Browser',
modified: DateTime.fromISO('2019-11-19T19:19:47.572-08:00')
},
},
repos: {},
errors: {}
});

const BrowserButtonContext = wrapInReduxContext(BrowserButton, store);

it('BrowserButton calls onClick when clicked', () => {
const onClick = jest.fn();
render(<BrowserButtonContext />);

const button = screen.getByRole('button');
if (button) {
button.addEventListener('click', onClick);
fireEvent.click(button);
}

expect(onClick).toHaveBeenCalled();
});
});
18 changes: 9 additions & 9 deletions __test__/CardComponent.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,41 +161,41 @@ describe('CardComponent', () => {
render(<CardContext {...cards['14']} />);

let backsideID = screen.queryByText(/ID:/i);
expect(backsideID).toBeNull();
expect(backsideID).not.toBeInTheDocument();

const flipButton = screen.getAllByRole('button')[0];
const flipButton = screen.getByRole('button', { name: /button-flip/i });
fireEvent.click(flipButton);

backsideID = screen.queryByText(/ID:/i);
expect(backsideID).not.toBeNull();
expect(backsideID).toBeInTheDocument();
});

it('Explorer Card renders a reverse side when the flip button is clicked', () => {
const CardContext = wrapInReduxContext(CardComponent, store);
render(<CardContext {...cards['573']} />);

let backsideName = screen.queryByText(/Name:/i);
expect(backsideName).toBeNull();
expect(backsideName).not.toBeInTheDocument();

const flipButton = screen.getAllByRole('button')[0];
fireEvent.click(flipButton);

backsideName = screen.queryByText(/Name:/i);
expect(backsideName).not.toBeNull();
expect(backsideName).toBeInTheDocument();
});

it('Diff Card renders a reverse side when the flip button is clicked', () => {
const CardContext = wrapInReduxContext(CardComponent, store);
render(<CardContext {...cards['22']} />);

let backsideName = screen.queryByText(/Name:/i);
expect(backsideName).toBeNull();
expect(backsideName).not.toBeInTheDocument();

const flipButton = screen.getAllByRole('button')[0];
fireEvent.click(flipButton);

backsideName = screen.queryByText(/Name:/i);
expect(backsideName).not.toBeNull();
expect(backsideName).toBeInTheDocument();
});

it('Browser Card renders a reverse side when the flip button is clicked', () => {
Expand All @@ -219,12 +219,12 @@ describe('CardComponent', () => {
render(<CardContext {...cards['46']} />);

let icon = screen.queryByRole('img');
expect(icon).not.toBeNull();
expect(icon).toBeInTheDocument();

const flipButton = screen.getAllByRole('button')[0];
fireEvent.click(flipButton);

icon = screen.queryByRole('img');
expect(icon).toBeNull();
expect(icon).not.toBeInTheDocument();
});
});
8 changes: 4 additions & 4 deletions __test__/DiffPickerDialog.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ describe('DiffPickerDialog', () => {
if (runDiffButton) fireEvent.click(runDiffButton);

// check the parameters of onClose fn to verify they match the card UUIDs
expect(onClose).toHaveBeenCalledWith(false, ["33", "14"]);
expect(onClose).toHaveBeenCalledWith(false, ['33', '14']);
});

it('DiffPickerDialog returns cancelled if no cards are selected', () => {
Expand All @@ -152,7 +152,7 @@ describe('DiffPickerDialog', () => {
fireEvent.keyDown(dialog, { key: 'Escape', keyCode: 27, which: 27 });

// check the parameters of onClose fn to verify that canceled parameter is true
expect(onClose).toHaveBeenCalledWith(true, ["", ""]);
expect(onClose).toHaveBeenCalledWith(true, ['', '']);
});

it('DiffPickerDialog returns cancelled if only the left card is selected', () => {
Expand All @@ -178,7 +178,7 @@ describe('DiffPickerDialog', () => {
fireEvent.keyDown(dialog, { key: 'Escape', keyCode: 27, which: 27 });

// check the parameters of onClose fn to verify that canceled parameter is true
expect(onClose).toHaveBeenCalledWith(true, ["", ""]);
expect(onClose).toHaveBeenCalledWith(true, ['', '']);
});

it('DiffPickerDialog returns cancelled if only the right card is selected', () => {
Expand All @@ -204,7 +204,7 @@ describe('DiffPickerDialog', () => {
fireEvent.keyDown(dialog, { key: 'Escape', keyCode: 27, which: 27 });

// check the parameters of onClose fn to verify that canceled parameter is true
expect(onClose).toHaveBeenCalledWith(true, ["", ""]);
expect(onClose).toHaveBeenCalledWith(true, ['', '']);
});

});
Expand Down
6 changes: 3 additions & 3 deletions __test__/Editor.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,17 @@ describe('Editor', () => {
render(<EditorContext metafileId='199' />);
const textBox = screen.queryByRole('textbox') as HTMLInputElement;

expect(textBox.value).toBe("");
expect(textBox).toHaveValue('');

textBox.focus();
fireEvent.change(textBox, { target: { value: 'var foo = 5;' } });

expect(textBox.value).toBe("var foo = 5;");
expect(textBox).toHaveValue('var foo = 5;');
});

it('Editor component should have a working reverse side', () => {
const EditorReverseContext = wrapInReduxContext(EditorReverse, store);
const card = store.getState().cards?.["57"];
const card = store.getState().cards?.['57'];
const wrapper = mount(<EditorReverseContext {...card} />, mountOptions);
const component = wrapper.find(EditorReverse).first();
expect(component).toBeDefined();
Expand Down
Loading

0 comments on commit 38869a4

Please sign in to comment.