Skip to content

Commit ae4dabf

Browse files
authored
Merge pull request #85 from oslabs-beta/staging
Merging spearmint 2.0 into original repo
2 parents 790368f + 0cb5e3d commit ae4dabf

File tree

74 files changed

+5298
-782
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+5298
-782
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
.env.development.local
1818
.env.test.local
1919
.env.production.local
20+
.env
2021

2122
/package-lock.json
2223
npm-debug.log*

.travis.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
language: node_js
2+
node_js:
3+
- 'node'
4+
cache:
5+
directories:
6+
- node_modules
7+
script:
8+
- npm run build
9+
deplloy:
10+
skip_cleanup: true
11+
on: master

README.md

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,34 @@
11
![](https://lh5.googleusercontent.com/5Gr2dZXHJdmIiASsPw9put-6mR20e4g1gOk-af4krREaJ7NqkZnqXLD5QgiotfNHYhGRh387HSqdhjRwxdwOvQzg9ChhfIrZz0FdxVu6gktBtG-sy1MX6Xq36Gmrzu_6G_K7LDQZ)
22

3-
Spearmint helps developers easily create functional React tests without writing any code. It dynamically converts user inputs into executable Jest test code by using DOM query selectors provided by the react-testing-library.
4-
5-
spearmint is currently under development! We just finished our MVP and are looking for beta testers. Please open a new issue with details to report a bug. Adding support to mock API requests, context and redux support are on the roadmap.
3+
Spearmint helps developers easily create functional React/Redux/Endpoint tests without writing any code. It dynamically converts user inputs into executable Jest test code by using DOM query selectors provided by @testing-library.
64

75
## How to use
86

9-
Download spearmint @ spearmintjs.com. Available for Mac OS and Windows. To run tests generated by spearmint install jest, jest-dom, react-testing-library, and test-data-bot in your dev dependencies.
7+
Download spearmint @ spearmintjs.com. Available for Mac OS and Windows.
8+
9+
To run React tests generated by spearmint, install the following in your dev dependencies.
10+
11+
npm i -D jest @testing-library/jest-dom @testing-library/react test-data-bot
12+
13+
To run Redux tests generated by spearmint, install the following in your dev dependencies, in addition to your React test installations above.
14+
15+
npm i -D redux-mock-store redux-thunk fetch-mock
16+
17+
To run Hooks / Context tests generated by spearmint, install the following in your dev dependencies, in addition to your React test installations above.
18+
19+
npm i -D @testing-library/react-hooks
20+
21+
To run Endpoint tests generated by spearmint, install the following in your dev dependencies.
1022

11-
npm i -D jest jest-dom @testing-library/react test-data-bot
23+
npm i -D jest supertest
1224

1325
## How it works
1426

15-
1. On the initial screen, enter the URL of your project and load your React application to start creating tests.
27+
1. On the initial screen, enter the URL of your project and load your application to start creating tests.
1628

1729
![](https://lh4.googleusercontent.com/CAFpoefRUUxgNosudQuc7gabSReFiI_puZ_WTjrzUSzB6pgOUdQ1babF2mxJql2lC8TQ-jjVLOgG5Qka8SUfF2fi-u2H9xSP7rZ_0Udpj-ISFPAY028UYKIUZcgOApnipVZwE7xh)
1830

19-
2. Utilize our auto-complete, drop-down options, and tooltips features to easily create arrangement, action, and assertion test statements.
31+
2. Utilize our auto-complete, drop-down options, and tooltips features to easily create arrangement, action, and assertion test statements for React; reducer, action creator, asynchronous action creator, and middleware test statements for Redux; and hooks, context, and endpoint test statements.
2032

2133
![](https://lh5.googleusercontent.com/5VYUlGG5VDdZxdZEh5aokuilhKRp8B5QyVmxvtW_abLYCAzYN-s-el1oV5WMtGuTzbEO2I6l8Ys_yK2gC0fCi8ISHwjh4LlgezsrPWd7mDEtLbPqBYf1J4pgkGmfIV4yq4I_dpQg)
2234

@@ -29,7 +41,12 @@ Download spearmint @ spearmintjs.com. Available for Mac OS and Windows. To run t
2941
## Team
3042

3143
> Alex [@apark0720](https://github.com/apark0720)  · 
32-
> Johnny [@johnny-lim](https://github.com/johnny-lim)  · 
44+
> Chloe [@HeyItsChloe](https://github.com/HeyItsChloe)  · 
45+
> Cornelius [@corneeltron](https://github.com/corneeltron)  · 
46+
> Dave [@davefranz](https://github.com/davefranz)  · 
47+
> Johnny [@johnny-lim](https://github.com/johnny-lim) <br />
3348
> Julie [@julicious100](https://github.com/julicious100) &nbsp;&middot;&nbsp;
49+
> Karen [@karenpinilla](https://github.com/karenpinilla) &nbsp;&middot;&nbsp;
50+
> Linda [@lcwish](https://github.com/lcwish) &nbsp;&middot;&nbsp;
3451
> Natlyn [@natlynp](https://github.com/natlynp) &nbsp;&middot;&nbsp;
35-
> Karen [@karenpinilla](https://github.com/karenpinilla)
52+
> Rachel [@rachethecreator](https://github.com/rachethecreator)

package.json

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
"homepage": "./",
1919
"private": true,
2020
"dependencies": {
21-
"concurrently": "^4.1.0",
22-
"cross-env": "^5.2.0",
21+
"concurrently": "^4.1.2",
22+
"cross-env": "^5.2.1",
2323
"electron-is-dev": "^1.1.0",
2424
"js-beautify": "^1.10.0",
2525
"monaco-editor": "^0.17.0",
@@ -32,12 +32,13 @@
3232
"react-monaco-editor": "^0.25.1",
3333
"react-scripts": "3.0.1",
3434
"typescript": "^3.5.1",
35-
"wait-on": "^3.2.0"
35+
"wait-on": "^3.3.0"
3636
},
3737
"scripts": {
3838
"react-start": "react-scripts start",
3939
"react-build": "react-scripts build",
4040
"test": "react-scripts test --env=jsdom",
41+
"test:watch": "jest --watch",
4142
"react-eject": "react-scripts eject",
4243
"electron-build": "electron-builder -mwl",
4344
"release": "npm run react-build && electron-builder --publish=always",
@@ -61,12 +62,13 @@
6162
},
6263
"devDependencies": {
6364
"@testing-library/react": "^8.0.1",
65+
"@testing-library/react-hooks": "^3.2.1",
6466
"electron": "^5.0.3",
6567
"electron-builder": "^20.43.0",
6668
"enzyme": "^3.10.0",
6769
"enzyme-adapter-react-16": "^1.14.0",
6870
"jest-dom": "^3.5.0",
69-
"react-test-renderer": "^16.8.6",
71+
"react-test-renderer": "^16.12.0",
7072
"spectron": "^5.0.0",
7173
"test-data-bot": "^0.8.0"
7274
}

src/App.jsx

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,27 @@ import React, { useReducer } from 'react';
22
import styles from './App.module.scss';
33
import { GlobalContext, globalState, globalReducer } from './context/globalReducer';
44
import { TestCaseContext, testCaseState, testCaseReducer } from './context/testCaseReducer';
5+
import {
6+
EndpointTestCaseContext,
7+
endpointTestCaseState,
8+
endpointTestCaseReducer,
9+
} from './context/endpointTestCaseReducer';
10+
import {
11+
ReduxTestCaseContext,
12+
reduxTestCaseState,
13+
reduxTestCaseReducer,
14+
} from './context/reduxTestCaseReducer';
15+
import {
16+
HooksTestCaseContext,
17+
hooksTestCaseState,
18+
hooksTestCaseReducer,
19+
} from './context/hooksTestCaseReducer';
20+
import {
21+
TestFileModalContext,
22+
testFileModalState,
23+
testFileModalReducer,
24+
} from './context/testFileModalReducer';
25+
526
import { MockDataContext, mockDataState, mockDataReducer } from './context/mockDataReducer';
627
import ProjectLoader from './containers/ProjectLoader/ProjectLoader';
728
import NavBar from './containers/NavBar/NavBar';
@@ -12,6 +33,23 @@ const App = () => {
1233
const [global, dispatchToGlobal] = useReducer(globalReducer, globalState);
1334
const [testCase, dispatchToTestCase] = useReducer(testCaseReducer, testCaseState);
1435
const [mockData, dispatchToMockData] = useReducer(mockDataReducer, mockDataState);
36+
const [endpointTestCase, dispatchToEndpointTestCase] = useReducer(
37+
endpointTestCaseReducer,
38+
endpointTestCaseState
39+
);
40+
41+
const [reduxTestCase, dispatchToReduxTestCase] = useReducer(
42+
reduxTestCaseReducer,
43+
reduxTestCaseState
44+
);
45+
const [hooksTestCase, dispatchToHooksTestCase] = useReducer(
46+
hooksTestCaseReducer,
47+
hooksTestCaseState
48+
);
49+
const [testFileModal, dispatchToTestFileModal] = useReducer(
50+
testFileModalReducer,
51+
testFileModalState
52+
);
1553

1654
if (!global.isProjectLoaded) {
1755
return (
@@ -23,13 +61,35 @@ const App = () => {
2361
);
2462
} else {
2563
return (
64+
/**
65+
* Wrap the components that we want to share the unique states with (ex: share testCase state with navbar & left panel (the two containers that hold the components that need testCaseRducer)) in the unique providers (ex: TestCaseContext.Provider).
66+
* You can only provide one value to a Provider.
67+
* - In order to avoid creating separate Contexts, wrap multiples in an array (ex: testCase and dispatchToTestCase).
68+
*
69+
*
70+
* NOTE: This concept is similar to Redux and how it provides the store to your top-level component and all of its children.
71+
* We just have to create separate providers for each reducer because we don’t have a global store ala Redux.
72+
*
73+
*
74+
* We access the value that we gave to the Provider through useContext
75+
*/
2676
<div id={global.isFileDirectoryOpen ? styles.appGridOpen : styles.appGridClose}>
2777
<GlobalContext.Provider value={[global, dispatchToGlobal]}>
2878
<TestCaseContext.Provider value={[testCase, dispatchToTestCase]}>
29-
<MockDataContext.Provider value={[mockData, dispatchToMockData]}>
30-
<NavBar />
31-
<LeftPanel />
32-
</MockDataContext.Provider>
79+
<ReduxTestCaseContext.Provider value={[reduxTestCase, dispatchToReduxTestCase]}>
80+
<EndpointTestCaseContext.Provider
81+
value={[endpointTestCase, dispatchToEndpointTestCase]}
82+
>
83+
<HooksTestCaseContext.Provider value={[hooksTestCase, dispatchToHooksTestCase]}>
84+
<TestFileModalContext.Provider value={[testFileModal, dispatchToTestFileModal]}>
85+
<MockDataContext.Provider value={[mockData, dispatchToMockData]}>
86+
<NavBar />
87+
<LeftPanel />
88+
</MockDataContext.Provider>
89+
</TestFileModalContext.Provider>
90+
</HooksTestCaseContext.Provider>
91+
</EndpointTestCaseContext.Provider>
92+
</ReduxTestCaseContext.Provider>
3393
</TestCaseContext.Provider>
3494
<RightPanel />
3595
</GlobalContext.Provider>

src/containers/LeftPanel/Action/Action.jsx

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const questionIcon = require('../../../assets/images/help-circle.png');
1111
const closeIcon = require('../../../assets/images/close.png');
1212
const dragIcon = require('../../../assets/images/drag-vertical.png');
1313

14+
// Action box in middle panel (testCase.jsx)
1415
const Action = ({ action, index, dispatchToTestCase }) => {
1516
const [{ mockData }, _] = useContext(MockDataContext);
1617
const handleChangeActionFields = (e, field) => {
@@ -36,23 +37,6 @@ const Action = ({ action, index, dispatchToTestCase }) => {
3637
return eventsWithValues.includes(eventType);
3738
};
3839

39-
// const dropDownMockOptions = [];
40-
// mockData.forEach(mockDatum => {
41-
// mockDatum.fieldKeys.forEach(key => {
42-
// dropDownMockOptions.push(`mock${mockDatum.name}.${key.fieldKey}`);
43-
// });
44-
// dropDownMockOptions.push(`[mock${mockDatum.name}]`);
45-
// dropDownMockOptions.push(`{mock${mockDatum.name}}`);
46-
// });
47-
48-
// let options = dropDownMockOptions.map(option => {
49-
// return (
50-
// <option id='eventValue' value={option}>
51-
// {option}
52-
// </option>
53-
// );
54-
// });
55-
5640
return (
5741
<Draggable draggableId={action.id.toString()} index={index}>
5842
{provided => (
@@ -171,4 +155,4 @@ const Action = ({ action, index, dispatchToTestCase }) => {
171155
);
172156
};
173157

174-
export default Action;
158+
export default Action;

src/containers/LeftPanel/Action/Action.module.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
letter-spacing: 0.5px;
99
}
1010

11+
1112
#close {
1213
float: right;
1314
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import React, { useContext } from 'react';
2+
import styles from '../ActionCreator/ActionCreator.module.scss';
3+
import { GlobalContext } from '../../../context/globalReducer';
4+
import {
5+
deleteActionCreator,
6+
updateActionCreator,
7+
updateActionsFilePath,
8+
updateTypesFilePath,
9+
} from '../../../context/reduxTestCaseActions';
10+
import { Draggable } from 'react-beautiful-dnd';
11+
const closeIcon = require('../../../assets/images/close.png');
12+
const dragIcon = require('../../../assets/images/drag-vertical.png');
13+
14+
const ActionCreator = ({ actionCreator, index, dispatchToReduxTestCase }) => {
15+
const [{ filePathMap }, _] = useContext(GlobalContext);
16+
const handleChangeActionCreatorFields = (e, field) => {
17+
let updatedActionCreator = { ...actionCreator };
18+
updatedActionCreator[field] = e.target.value;
19+
dispatchToReduxTestCase(updateActionCreator(updatedActionCreator));
20+
};
21+
22+
const handleClickDeleteActionCreator = e => {
23+
dispatchToReduxTestCase(deleteActionCreator(actionCreator.id));
24+
};
25+
26+
const handleChangeActionsFileName = e => {
27+
const actionsFileName = e.target.value;
28+
const filePath = filePathMap[actionsFileName] || '';
29+
dispatchToReduxTestCase(updateActionsFilePath(actionsFileName, filePath));
30+
};
31+
32+
const handleChangeTypesFileName = e => {
33+
const typesFileName = e.target.value;
34+
const filePath = filePathMap[typesFileName] || '';
35+
dispatchToReduxTestCase(updateTypesFilePath(typesFileName, filePath));
36+
};
37+
38+
return (
39+
<Draggable draggableId={actionCreator.id.toString()} index={index}>
40+
{provided => (
41+
<div
42+
ref={provided.innerRef}
43+
{...provided.draggableProps}
44+
{...provided.dragHandleProps}
45+
id={styles.actionCreator}
46+
>
47+
<img
48+
src={closeIcon}
49+
id={styles.close}
50+
alt='close'
51+
onClick={handleClickDeleteActionCreator}
52+
/>
53+
54+
<div id={styles.actionCreatorHeader}>
55+
<img src={dragIcon} alt='drag' />
56+
<h3>Action Creator</h3>
57+
</div>
58+
59+
<div id={styles.filesFlexBox}>
60+
<div id={styles.files}>
61+
<label htmlFor='actionsFolder'>Import Actions From</label>
62+
<input
63+
type='text'
64+
id='actionsFolder'
65+
value={actionCreator.actionsFile}
66+
onChange={handleChangeActionsFileName}
67+
placeholder='File Name'
68+
/>
69+
</div>
70+
71+
<div id={styles.files}>
72+
<label htmlFor='typesFolder'>Import Action Types From</label>
73+
<input
74+
type='text'
75+
id='typesFolder'
76+
value={actionCreator.typesFile}
77+
onChange={handleChangeTypesFileName}
78+
placeholder='File Name'
79+
/>
80+
</div>
81+
</div>
82+
83+
<div id={styles.actionFlexBox}>
84+
<div id={styles.actions}>
85+
<label htmlFor='actionCreatorFunc'>Action Creator</label>
86+
<input
87+
type='text'
88+
id='actionCreatorFunc'
89+
onChange={e => handleChangeActionCreatorFields(e, 'actionCreatorFunc')}
90+
placeholder='e.g. addTodo'
91+
/>
92+
</div>
93+
94+
<div id={styles.actions}>
95+
<label htmlFor='actionType'>Action Type</label>
96+
<input
97+
type='text'
98+
id='actionType'
99+
onChange={e => handleChangeActionCreatorFields(e, 'actionType')}
100+
placeholder='e.g. ADD_TODO'
101+
/>
102+
</div>
103+
</div>
104+
105+
<div id={styles.payloadFlexBox}>
106+
<div id={styles.payloadKey}>
107+
<label htmlFor='payloadKey'>Payload Key</label>
108+
<input
109+
type='text'
110+
id='payloadKey'
111+
onChange={e => handleChangeActionCreatorFields(e, 'payloadKey')}
112+
placeholder='e.g. todo'
113+
/>
114+
</div>
115+
116+
<div id={styles.payloadType}>
117+
<label htmlFor='payloadType'>Payload Type</label>
118+
<select
119+
id='payloadType'
120+
onChange={e => handleChangeActionCreatorFields(e, 'payloadType')}
121+
>
122+
<option value='' />
123+
<option value='word'>word</option>
124+
<option value='words'>words</option>
125+
<option value='number'>number</option>
126+
<option value='arrayElement'>arrayElement</option>
127+
<option value='objectElement'>objectElement</option>
128+
</select>
129+
</div>
130+
</div>
131+
</div>
132+
)}
133+
</Draggable>
134+
);
135+
};
136+
137+
export default ActionCreator;

0 commit comments

Comments
 (0)