automock 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.travis.yml +11 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/LISENCE.txt +22 -0
- data/README.md +110 -0
- data/Rakefile +11 -0
- data/automock/data/test.json +1 -0
- data/automock/data/test2.json +1 -0
- data/automock.gemspec +27 -0
- data/bin/console +14 -0
- data/bin/server +3 -0
- data/bin/setup +13 -0
- data/lib/automock/response_mock.rb +55 -0
- data/lib/automock/rspec.rb +11 -0
- data/lib/automock/version.rb +3 -0
- data/lib/automock.rb +24 -0
- data/lib/tasks/automock.rake +31 -0
- data/server/.babelrc +3 -0
- data/server/.eslintrc +104 -0
- data/server/.flowconfig +11 -0
- data/server/.gitignore +4 -0
- data/server/app/db/database.json +10 -0
- data/server/app/db/sequelize.js +4 -0
- data/server/app/index.js +75 -0
- data/server/app/models/selected_file.js +11 -0
- data/server/app/proxy_server.js +50 -0
- data/server/assets/index.html +12 -0
- data/server/assets/javascripts/actions/mock_files_actions.js +18 -0
- data/server/assets/javascripts/actions/selected_files_actions.js +46 -0
- data/server/assets/javascripts/components/file_list.react.js +23 -0
- data/server/assets/javascripts/components/select_buttons.react.js +18 -0
- data/server/assets/javascripts/components/selectable_lists.react.js +44 -0
- data/server/assets/javascripts/containers/app.react.js +56 -0
- data/server/assets/javascripts/index.js +23 -0
- data/server/assets/javascripts/reducers/index.js +7 -0
- data/server/assets/javascripts/reducers/mock_files.js +11 -0
- data/server/assets/javascripts/reducers/selected_files.js +15 -0
- data/server/assets/stylesheets/application.scss +4 -0
- data/server/assets/stylesheets/components/_file_list.scss +9 -0
- data/server/assets/stylesheets/components/_select_buttons.scss +6 -0
- data/server/assets/stylesheets/components/_selectable_list.scss +3 -0
- data/server/bin/server +13 -0
- data/server/gulpfile.coffee +35 -0
- data/server/migrations/20160101185711-add-selected-files.js +15 -0
- data/server/migrations/20160102233558-add-columns-to-selected-files.js +17 -0
- data/server/package.json +58 -0
- data/server/test/fixtures/mock/api/v1/api_test.json +1 -0
- data/server/test/fixtures/mock/test.json +1 -0
- data/server/test/request/common_hooks.js +20 -0
- data/server/test/request/mock_files_test.js +34 -0
- data/server/test/request/selected_files_test.js +63 -0
- metadata +182 -0
data/server/app/index.js
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const express = require('express');
|
4
|
+
const app = express();
|
5
|
+
const recursive = require('recursive-readdir');
|
6
|
+
const path = require('path');
|
7
|
+
const SelectedFile = require('./models/selected_file');
|
8
|
+
const bodyParser = require('body-parser');
|
9
|
+
const fs = require('fs');
|
10
|
+
|
11
|
+
app.use(express.static(__dirname + '/assets'));
|
12
|
+
app.use(bodyParser.urlencoded());
|
13
|
+
app.use(bodyParser.json());
|
14
|
+
let proxyServer;
|
15
|
+
|
16
|
+
app.get('/mock_files', function(_req, res){
|
17
|
+
recursive(process.env.AUTOMOCK_DATA_PATH, (_err, filePaths) => {
|
18
|
+
Promise.all(filePaths.map((filePath) =>
|
19
|
+
new Promise((resolve) => {
|
20
|
+
fs.readFile(filePath, 'utf8', (_err2, text) => {
|
21
|
+
const mockData = JSON.parse(text);
|
22
|
+
mockData.name = path.relative(process.env.AUTOMOCK_DATA_PATH, filePath);
|
23
|
+
resolve(mockData);
|
24
|
+
});
|
25
|
+
})
|
26
|
+
)).then((files) => {
|
27
|
+
res.status(200).send(files);
|
28
|
+
});
|
29
|
+
});
|
30
|
+
});
|
31
|
+
|
32
|
+
app.get('/selected_files', function(req, res){
|
33
|
+
SelectedFile.findAll().
|
34
|
+
then((files) => {
|
35
|
+
const response = files.map((file) => {
|
36
|
+
return {
|
37
|
+
id: file.id,
|
38
|
+
name: file.name
|
39
|
+
};
|
40
|
+
});
|
41
|
+
res.status(200).send(response);
|
42
|
+
});
|
43
|
+
});
|
44
|
+
|
45
|
+
app.post('/selected_files', function(req, res){
|
46
|
+
SelectedFile.create({
|
47
|
+
name: req.body.name,
|
48
|
+
uri: req.body.uri,
|
49
|
+
method: req.body.method
|
50
|
+
}).then((selectedFile) => {
|
51
|
+
res.status(201).send(selectedFile);
|
52
|
+
if (proxyServer) {
|
53
|
+
proxyServer.loadSelectedFiles();
|
54
|
+
}
|
55
|
+
});
|
56
|
+
});
|
57
|
+
|
58
|
+
app.delete('/selected_files/:id', function(req, res){
|
59
|
+
SelectedFile.destroy({ where: { id: req.params.id } }).then(() => {
|
60
|
+
res.status(204).send();
|
61
|
+
if (proxyServer) {
|
62
|
+
proxyServer.loadSelectedFiles();
|
63
|
+
}
|
64
|
+
});
|
65
|
+
});
|
66
|
+
|
67
|
+
if (!module.parent) {
|
68
|
+
app.listen(process.env.AUTOMOCK_PORT || 8000);
|
69
|
+
const ProxyServer = require('./proxy_server');
|
70
|
+
proxyServer = new ProxyServer();
|
71
|
+
proxyServer.start();
|
72
|
+
}
|
73
|
+
|
74
|
+
|
75
|
+
module.exports = app;
|
@@ -0,0 +1,11 @@
|
|
1
|
+
const Sequelize = require('sequelize');
|
2
|
+
const sequelize = require('./../db/sequelize');
|
3
|
+
const SelectedFile = sequelize.define('selected_files', {
|
4
|
+
name: { type: Sequelize.STRING },
|
5
|
+
method: { type: Sequelize.STRING },
|
6
|
+
uri: { type: Sequelize.STRING }
|
7
|
+
}, {
|
8
|
+
freezeTableName: true
|
9
|
+
});
|
10
|
+
|
11
|
+
module.exports = SelectedFile;
|
@@ -0,0 +1,50 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const httpProxy = require('http-proxy');
|
4
|
+
const SelectedFile = require('./models/selected_file');
|
5
|
+
const _ = require('underscore');
|
6
|
+
const fs = require('fs');
|
7
|
+
|
8
|
+
class ProxyServer {
|
9
|
+
constructor() {
|
10
|
+
const targetPort = process.env.AUTOMOCK_TARGET_PORT || 3000;
|
11
|
+
const proxyPort = process.env.AUTOMOCK_PROXY_PORT || 8001;
|
12
|
+
this.server = httpProxy.createProxyServer({
|
13
|
+
target:`http://localhost:${targetPort}`
|
14
|
+
}).listen(proxyPort);
|
15
|
+
this.selectedFiles = [];
|
16
|
+
}
|
17
|
+
|
18
|
+
loadSelectedFiles() {
|
19
|
+
SelectedFile.findAll().then((records) => {
|
20
|
+
this.selectedFiles = records;
|
21
|
+
});
|
22
|
+
}
|
23
|
+
|
24
|
+
start() {
|
25
|
+
this.loadSelectedFiles();
|
26
|
+
this.server.on('proxyRes', (_proxyRes, req, res) => {
|
27
|
+
const lookupedSelectedFile = _.find(this.selectedFiles, (selectedFile) =>
|
28
|
+
(selectedFile.uri === req.url) && (selectedFile.method === req.method)
|
29
|
+
);
|
30
|
+
if (lookupedSelectedFile) {
|
31
|
+
const write = res.write, writeHead = res.writeHead, end = res.end, bufs = [];
|
32
|
+
res.writeHead = (_status, _headers) => {
|
33
|
+
res.write = (body) => {
|
34
|
+
bufs.push(body);
|
35
|
+
};
|
36
|
+
res.end = () => {
|
37
|
+
fs.readFile(`${process.env.AUTOMOCK_DATA_PATH}/${lookupedSelectedFile.name}`, 'utf8', function (_err, text) {
|
38
|
+
const mockData = JSON.parse(text);
|
39
|
+
writeHead.call(res, mockData.status, mockData.response_header);
|
40
|
+
write.call(res, mockData.response_body);
|
41
|
+
end.call(res);
|
42
|
+
});
|
43
|
+
};
|
44
|
+
};
|
45
|
+
}
|
46
|
+
});
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
module.exports = ProxyServer;
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<title>automock</title>
|
6
|
+
<link rel="stylesheet" href="stylesheets/application.css" media="screen">
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<div id="application"></div>
|
10
|
+
<script src="bundle.js"></script>
|
11
|
+
</body>
|
12
|
+
</html>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
/* flow */
|
2
|
+
|
3
|
+
import request from 'superagent';
|
4
|
+
export const GET_MOCK_FILES = 'GET_MOCK_FILES';
|
5
|
+
|
6
|
+
export function getMockFiles() {
|
7
|
+
return (dispatch) => {
|
8
|
+
request.
|
9
|
+
get('./mock_files').
|
10
|
+
end((_err, res) => {
|
11
|
+
dispatch({
|
12
|
+
type: GET_MOCK_FILES,
|
13
|
+
mockFiles: res.body
|
14
|
+
});
|
15
|
+
}
|
16
|
+
);
|
17
|
+
};
|
18
|
+
}
|
@@ -0,0 +1,46 @@
|
|
1
|
+
/* flow */
|
2
|
+
|
3
|
+
import request from 'superagent';
|
4
|
+
export const GET_SELECTED_FILES = 'GET_SELECTED_FILES';
|
5
|
+
export const CREATE_SELECTED_FILES = 'CREATE_SELECTED_FILES';
|
6
|
+
export const DELETE_SELECTED_FILES = 'DELETE_SELECTED_FILES';
|
7
|
+
|
8
|
+
export function getSelectedFiles() {
|
9
|
+
return (dispatch) => {
|
10
|
+
request.
|
11
|
+
get('/selected_files').
|
12
|
+
end((_err, res) => {
|
13
|
+
dispatch({
|
14
|
+
type: GET_SELECTED_FILES,
|
15
|
+
selectedFiles: res.body
|
16
|
+
});
|
17
|
+
}
|
18
|
+
);
|
19
|
+
};
|
20
|
+
}
|
21
|
+
|
22
|
+
export function createSelectedFile(file) {
|
23
|
+
return (dispatch) => {
|
24
|
+
request.
|
25
|
+
post('/selected_files').
|
26
|
+
send(file).
|
27
|
+
end((_err, res) => {
|
28
|
+
dispatch({
|
29
|
+
type: CREATE_SELECTED_FILES,
|
30
|
+
selectedFile: res.body
|
31
|
+
});
|
32
|
+
}
|
33
|
+
);
|
34
|
+
};
|
35
|
+
}
|
36
|
+
|
37
|
+
export function deleteSelectedFile(id) {
|
38
|
+
return (dispatch) => {
|
39
|
+
request.
|
40
|
+
delete(`/selected_files/${id}`).
|
41
|
+
end((_err, _res) => {
|
42
|
+
dispatch({ type: DELETE_SELECTED_FILES, id });
|
43
|
+
}
|
44
|
+
);
|
45
|
+
};
|
46
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
|
3
|
+
export default class FileList extends React.Component {
|
4
|
+
handleSelect(e) {
|
5
|
+
const selectedFile = this.props.files.filter((file) => file.name === e.target.value).toArray()[0];
|
6
|
+
this.props.onChange(selectedFile);
|
7
|
+
}
|
8
|
+
render() {
|
9
|
+
const options = this.props.files.map((file) =>
|
10
|
+
<option value={file.name} key={file.name}>{file.name}</option>
|
11
|
+
);
|
12
|
+
return(
|
13
|
+
<div className="file-list col-xs-5">
|
14
|
+
<div className="title">{this.props.title}</div>
|
15
|
+
<div>
|
16
|
+
<select size="10" onChange={this.handleSelect.bind(this)}>
|
17
|
+
{options}
|
18
|
+
</select>
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
);
|
22
|
+
}
|
23
|
+
};
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
|
3
|
+
export default class SelectButtons extends React.Component {
|
4
|
+
handleClickSelectButton() {
|
5
|
+
this.props.onClickSelectButton(this.props.selectedFromNotSelectedFiles);
|
6
|
+
}
|
7
|
+
handleClickUnselectButton() {
|
8
|
+
this.props.onClickUnselectButton(this.props.selectedFromSelectedFiles.id);
|
9
|
+
}
|
10
|
+
render() {
|
11
|
+
return(
|
12
|
+
<div className="select-buttons col-xs-1">
|
13
|
+
<button className="btn btn-primary" onClick={this.handleClickSelectButton.bind(this)}>→</button>
|
14
|
+
<button className="btn" onClick={this.handleClickUnselectButton.bind(this)}>←</button>
|
15
|
+
</div>
|
16
|
+
);
|
17
|
+
}
|
18
|
+
};
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import FileList from './file_list';
|
3
|
+
import SelectButtons from './select_buttons';
|
4
|
+
|
5
|
+
export default class SelectableLists extends React.Component {
|
6
|
+
constructor() {
|
7
|
+
super();
|
8
|
+
this.state = {
|
9
|
+
selectedFromNotSelectedFiles: '',
|
10
|
+
selectedFromSelectedFiles: ''
|
11
|
+
};
|
12
|
+
}
|
13
|
+
|
14
|
+
handleSelectFromNotSelectedFiles(selectedFile) {
|
15
|
+
this.setState({ selectedFromNotSelectedFiles: selectedFile });
|
16
|
+
}
|
17
|
+
|
18
|
+
handleSelectFromSelectedFiles(selectedFile) {
|
19
|
+
this.setState({ selectedFromSelectedFiles: selectedFile });
|
20
|
+
}
|
21
|
+
|
22
|
+
render() {
|
23
|
+
const { selectedFiles, unselectedFiles } = this.props;
|
24
|
+
return(
|
25
|
+
<div className="selectable-lists row">
|
26
|
+
<FileList
|
27
|
+
title={"not selected files"}
|
28
|
+
files={unselectedFiles}
|
29
|
+
onChange={this.handleSelectFromNotSelectedFiles.bind(this)}
|
30
|
+
/>
|
31
|
+
<SelectButtons
|
32
|
+
onClickSelectButton={this.props.onCreateSelectedFile}
|
33
|
+
onClickUnselectButton={this.props.onDeleteSelectedFile}
|
34
|
+
{...this.state}
|
35
|
+
/>
|
36
|
+
<FileList
|
37
|
+
title={"selected files"}
|
38
|
+
files={selectedFiles}
|
39
|
+
onChange={this.handleSelectFromSelectedFiles.bind(this)}
|
40
|
+
/>
|
41
|
+
</div>
|
42
|
+
);
|
43
|
+
}
|
44
|
+
};
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { bindActionCreators } from 'redux';
|
3
|
+
import { connect } from 'react-redux';
|
4
|
+
import * as SelectedFilesActions from '../actions/selected_files_actions';
|
5
|
+
import * as MockFilesActions from '../actions/mock_files_actions';
|
6
|
+
import SelectableLists from './../components/selectable_lists';
|
7
|
+
import assign from 'object-assign';
|
8
|
+
import _ from 'underscore';
|
9
|
+
|
10
|
+
class AppContainer extends React.Component {
|
11
|
+
componentDidMount() {
|
12
|
+
const { getSelectedFiles, getMockFiles } = this.props;
|
13
|
+
getSelectedFiles();
|
14
|
+
getMockFiles();
|
15
|
+
}
|
16
|
+
|
17
|
+
handleCreateSelectedFile(file) {
|
18
|
+
const { createSelectedFile } = this.props;
|
19
|
+
createSelectedFile(file);
|
20
|
+
}
|
21
|
+
|
22
|
+
handleDeleteSelectedFile(id) {
|
23
|
+
const { deleteSelectedFile } = this.props;
|
24
|
+
deleteSelectedFile(id);
|
25
|
+
}
|
26
|
+
|
27
|
+
render() {
|
28
|
+
const { selectedFiles, mockFiles } = this.props;
|
29
|
+
const selectedFileNames = selectedFiles.map((file) => file.name).toArray();
|
30
|
+
const unselectedFiles = mockFiles.filter((file) => !_.includes(selectedFileNames, file.name));
|
31
|
+
return (
|
32
|
+
<div className="container">
|
33
|
+
<SelectableLists
|
34
|
+
selectedFiles={selectedFiles}
|
35
|
+
unselectedFiles={unselectedFiles}
|
36
|
+
onCreateSelectedFile={this.handleCreateSelectedFile.bind(this)}
|
37
|
+
onDeleteSelectedFile={this.handleDeleteSelectedFile.bind(this)}
|
38
|
+
/>
|
39
|
+
</div>
|
40
|
+
);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
function mapStateToProps(state) {
|
45
|
+
return {
|
46
|
+
selectedFiles: state.selectedFiles,
|
47
|
+
mockFiles: state.mockFiles
|
48
|
+
};
|
49
|
+
}
|
50
|
+
|
51
|
+
function mapDispatchToProps(dispatch) {
|
52
|
+
const actions = assign({}, SelectedFilesActions, MockFilesActions);
|
53
|
+
return bindActionCreators(actions, dispatch);
|
54
|
+
}
|
55
|
+
|
56
|
+
export default connect(mapStateToProps, mapDispatchToProps)(AppContainer);
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { render } from 'react-dom';
|
3
|
+
import { createStore, applyMiddleware } from 'redux';
|
4
|
+
import { Provider } from 'react-redux';
|
5
|
+
import App from './containers/app';
|
6
|
+
import reducers from './reducers';
|
7
|
+
import thunk from 'redux-thunk';
|
8
|
+
import logger from 'redux-logger';
|
9
|
+
|
10
|
+
const middleware = process.env.NODE_ENV === 'production' ?
|
11
|
+
[ thunk ] :
|
12
|
+
[ thunk, logger() ];
|
13
|
+
|
14
|
+
const createStoreWithMiddleware = applyMiddleware(...middleware)(createStore);
|
15
|
+
const store = createStoreWithMiddleware(reducers);
|
16
|
+
|
17
|
+
const rootElement = document.getElementById('application');
|
18
|
+
render(
|
19
|
+
<Provider store={store}>
|
20
|
+
<App />
|
21
|
+
</Provider>,
|
22
|
+
rootElement
|
23
|
+
);
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { List } from 'immutable';
|
2
|
+
import { GET_MOCK_FILES } from '../actions/mock_files_actions';
|
3
|
+
|
4
|
+
export default function mockFiles(state = List(), action) {
|
5
|
+
switch (action.type) {
|
6
|
+
case GET_MOCK_FILES:
|
7
|
+
return List(action.mockFiles);
|
8
|
+
default:
|
9
|
+
return state;
|
10
|
+
}
|
11
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { List } from 'immutable';
|
2
|
+
import { GET_SELECTED_FILES, CREATE_SELECTED_FILES, DELETE_SELECTED_FILES } from '../actions/selected_files_actions';
|
3
|
+
|
4
|
+
export default function selectedFiles(state = List(), action) {
|
5
|
+
switch (action.type) {
|
6
|
+
case GET_SELECTED_FILES:
|
7
|
+
return List(action.selectedFiles);
|
8
|
+
case CREATE_SELECTED_FILES:
|
9
|
+
return state.push(action.selectedFile);
|
10
|
+
case DELETE_SELECTED_FILES:
|
11
|
+
return state.filter((file) => file.id !== action.id);
|
12
|
+
default:
|
13
|
+
return state;
|
14
|
+
}
|
15
|
+
}
|
data/server/bin/server
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
gulp = require 'gulp'
|
2
|
+
babelify = require 'babelify'
|
3
|
+
browserify = require 'browserify'
|
4
|
+
source = require 'vinyl-source-stream'
|
5
|
+
sass = require 'gulp-sass'
|
6
|
+
seq = require 'run-sequence'
|
7
|
+
|
8
|
+
gulp.path =
|
9
|
+
src: 'assets'
|
10
|
+
dist: 'app/assets'
|
11
|
+
|
12
|
+
gulp.task 'build', ->
|
13
|
+
seq ['build:html', 'build:browserify', 'build:scss']
|
14
|
+
|
15
|
+
gulp.task 'build:html', ->
|
16
|
+
gulp.src "#{@path.src}/**/*.html"
|
17
|
+
.pipe gulp.dest(@path.dist)
|
18
|
+
|
19
|
+
gulp.task 'build:browserify', ->
|
20
|
+
browserify(
|
21
|
+
entries: ["#{@path.src}/javascripts/index.js"]
|
22
|
+
extensions: ['.js', '.react.js']
|
23
|
+
).transform(babelify)
|
24
|
+
.bundle()
|
25
|
+
.pipe source 'bundle.js'
|
26
|
+
.pipe gulp.dest(@path.dist)
|
27
|
+
|
28
|
+
gulp.task 'build:scss', ->
|
29
|
+
gulp.src "#{@path.src}/**/*.scss"
|
30
|
+
.pipe sass({ includePaths: [ 'node_modules' ] }).on('error', sass.logError)
|
31
|
+
.pipe gulp.dest(@path.dist)
|
32
|
+
|
33
|
+
gulp.task 'watch', ['build'], ->
|
34
|
+
gulp.watch("#{@path.src}/**/*.js", ['build:browserify'])
|
35
|
+
gulp.watch("#{@path.src}/**/*.scss", ['build:scss'])
|
@@ -0,0 +1,15 @@
|
|
1
|
+
var dbm = global.dbm || require('db-migrate');
|
2
|
+
var type = dbm.dataType;
|
3
|
+
|
4
|
+
exports.up = function(db, callback) {
|
5
|
+
db.createTable('selected_files', {
|
6
|
+
id: { type: 'int', primaryKey: true, autoIncrement: true },
|
7
|
+
name: { type: 'string', unique: true, notNull: 'true' },
|
8
|
+
createdAt: { type: 'datetime' },
|
9
|
+
updatedAt: { type: 'datetime' }
|
10
|
+
}, callback);
|
11
|
+
};
|
12
|
+
|
13
|
+
exports.down = function(db, callback) {
|
14
|
+
callback();
|
15
|
+
};
|
@@ -0,0 +1,17 @@
|
|
1
|
+
var dbm = global.dbm || require('db-migrate');
|
2
|
+
var type = dbm.dataType;
|
3
|
+
var async = require('async');
|
4
|
+
|
5
|
+
exports.up = function(db, callback) {
|
6
|
+
async.series([
|
7
|
+
db.addColumn.bind(db, 'selected_files', 'method', { type: 'string', notNull: true, defaultValue: 'dummy' }),
|
8
|
+
db.addColumn.bind(db, 'selected_files', 'uri', { type: 'string', notNull: true, defaultValue: 'dummy' })
|
9
|
+
], callback);
|
10
|
+
};
|
11
|
+
|
12
|
+
exports.down = function(db, callback) {
|
13
|
+
async.series([
|
14
|
+
db.removeColumn.bind(db, 'selected_files', 'method'),
|
15
|
+
db.removeColumn.bind(db, 'selected_files', 'uri')
|
16
|
+
], callback);
|
17
|
+
};
|
data/server/package.json
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
{
|
2
|
+
"name": "automock",
|
3
|
+
"devDependencies": {
|
4
|
+
"async": "^1.5.1",
|
5
|
+
"babel": "^6.1.18",
|
6
|
+
"babel-cli": "^6.2.0",
|
7
|
+
"babel-core": "^6.3.26",
|
8
|
+
"babel-preset-es2015": "^6.1.18",
|
9
|
+
"babel-preset-react": "^6.3.13",
|
10
|
+
"babelify": "^7.2.0",
|
11
|
+
"browserify": "^12.0.1",
|
12
|
+
"coffee-script": "^1.10.0",
|
13
|
+
"db-migrate": "^0.9.23",
|
14
|
+
"gulp": "^3.9.0",
|
15
|
+
"gulp-sass": "^2.1.1",
|
16
|
+
"http-proxy": "^1.12.0",
|
17
|
+
"mocha": "^2.3.4",
|
18
|
+
"power-assert": "^1.2.0",
|
19
|
+
"redux-devtools": "^3.0.1",
|
20
|
+
"run-sequence": "^1.1.5",
|
21
|
+
"supertest": "^1.1.0",
|
22
|
+
"vinyl-source-stream": "^1.1.0"
|
23
|
+
},
|
24
|
+
"dependencies": {
|
25
|
+
"body-parser": "^1.14.2",
|
26
|
+
"bootstrap": "^4.0.0-alpha.2",
|
27
|
+
"express": "^4.13.3",
|
28
|
+
"immutable": "^3.7.6",
|
29
|
+
"object-assign": "^4.0.1",
|
30
|
+
"react": "^0.14.3",
|
31
|
+
"react-dom": "^0.14.3",
|
32
|
+
"react-redux": "^4.0.5",
|
33
|
+
"recursive-readdir": "^1.3.0",
|
34
|
+
"redux": "^3.0.5",
|
35
|
+
"redux-logger": "^2.3.1",
|
36
|
+
"redux-thunk": "^1.0.2",
|
37
|
+
"sequelize": "^3.15.1",
|
38
|
+
"sqlite3": "^3.1.1",
|
39
|
+
"superagent": "^1.6.1",
|
40
|
+
"underscore": "^1.8.3"
|
41
|
+
},
|
42
|
+
"scripts": {
|
43
|
+
"test": "mocha --require babel-core/register --recursive test",
|
44
|
+
"build": "gulp build",
|
45
|
+
"watch": "gulp watch"
|
46
|
+
},
|
47
|
+
"repository": {
|
48
|
+
"type": "git",
|
49
|
+
"url": "git+https://github.com/joe-re/automock.git"
|
50
|
+
},
|
51
|
+
"keywords": [],
|
52
|
+
"author": "",
|
53
|
+
"license": "MIT",
|
54
|
+
"bugs": {
|
55
|
+
"url": "https://github.com/joe-re/automock/issues"
|
56
|
+
},
|
57
|
+
"homepage": "https://github.com/joe-re/automock#readme"
|
58
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"description":"description","method":"GET","uri":"/api/v1/users","status": "200","response_body":"{\"users\":[{\"username\":\"sample\",\"email\":\"sample@ggg.com\"}]}"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"description":"api description","method":"POST","uri":"/api/v1/users","status": "201","response_body":"{\"users\":[{\"username\":\"sample\",\"email\":\"sample@ggg.com\"}]}"}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
process.env.AUTOMOCK_DATA_PATH=__dirname + '/../fixtures/mock';
|
2
|
+
process.env.NODE_ENV='test';
|
3
|
+
|
4
|
+
const sequelize = require('../../app/db/sequelize');
|
5
|
+
const SelectedFile = require('../../app/models/selected_file');
|
6
|
+
|
7
|
+
before(function() {
|
8
|
+
const execSync = require('child_process').execSync;
|
9
|
+
execSync('node ./node_modules/db-migrate/bin/db-migrate up --config app/db/database.json -e test');
|
10
|
+
});
|
11
|
+
|
12
|
+
beforeEach(function () {
|
13
|
+
SelectedFile.truncate();
|
14
|
+
});
|
15
|
+
|
16
|
+
after(function() {
|
17
|
+
sequelize.
|
18
|
+
getQueryInterface().
|
19
|
+
dropAllTables();
|
20
|
+
});
|
@@ -0,0 +1,34 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
require('./common_hooks');
|
4
|
+
const request = require('supertest');
|
5
|
+
|
6
|
+
let server;
|
7
|
+
describe('GET /mock_files', function () {
|
8
|
+
beforeEach(function () {
|
9
|
+
server = require('./../../app/index');
|
10
|
+
});
|
11
|
+
it('receives mock_files and 200', function testSlash(done) {
|
12
|
+
request(server).
|
13
|
+
get('/mock_files').
|
14
|
+
expect(200, [
|
15
|
+
{
|
16
|
+
description: 'api description',
|
17
|
+
method: 'POST',
|
18
|
+
name: 'test.json',
|
19
|
+
status: '201',
|
20
|
+
response_body: '{\"users\":[{\"username\":\"sample\",\"email\":\"sample@ggg.com\"}]}',
|
21
|
+
uri: '/api/v1/users'
|
22
|
+
},
|
23
|
+
{
|
24
|
+
description: 'description',
|
25
|
+
method: 'GET',
|
26
|
+
name: 'api/v1/api_test.json',
|
27
|
+
status: '200',
|
28
|
+
response_body: '{\"users\":[{\"username\":\"sample\",\"email\":\"sample@ggg.com\"}]}',
|
29
|
+
uri: '/api/v1/users'
|
30
|
+
}
|
31
|
+
], done);
|
32
|
+
});
|
33
|
+
});
|
34
|
+
|