Failing test with bookshelf.js and bookshelf-validate - promise

I am new to node and I am just attempting at writing a simple backend blog API. I am using bookshelf.js as the ORM and I am attempting to use bookshelf-validate in order to enforce requirements on an Article model that I made. The validations I have included with the Article model are merely the isRequired validations on all fields (fields being title, author, and body). One of my tests creates a new article with all the fields defined and the test is failing. Here is my code,
//here is the bookshelf model
const Bookshelf = require('../config/bookshelf.config');
const Article = Bookshelf.Model.extend({
tableName: 'articles',
hasTimestamps: true,
validations: {
title: {
isRequired: true
},
author: {
isRequired: true
},
body: {
isRequired: true
}
}
});
module.exports = Bookshelf.model('Article', Article);
//test file below
process.env.NODE_ENV = 'test';
const chaiAsPromised = require('chai-as-promised');
const { expect, assert } = require('chai').use(chaiAsPromised);
const knex = require('knex')(require('../knexfile')[process.env.NODE_ENV]);
const Article = require('../models/article');
describe('Articles', function () {
beforeEach(function () {
return knex.migrate.rollback()
.then(function () {
return knex.migrate.latest();
});
});
after(function () {
return knex.migrate.rollback();
});
describe('test db', function () {
it('should not have any models at start of test suite', function () {
Article.forge().fetch().then(function (results) {
expect(results).to.equal(null);
});
});
it('should save a model to the db', function () {
const article = new Article({
title: 'first blog',
author: 'john doe',
body: 'blah blah'
}).save();
return expect(article).to.be.fulfilled;
});
});
});
Here is the gist as well https://gist.github.com/Euklidian-Space/bf10fd1a72bec9190867854d1ea309d9
Thanks in advance.

Your should save a model to the db test is not taking asynchronicity into account. It may save the entry but the expect() call may come too early to get the fulfilled promise.
So replace
it('should save a model to the db', function () {
const article = new Article({
title: 'first blog',
author: 'john doe',
body: 'blah blah'
}).save();
return expect(article).to.be.fulfilled;
});
by something like
it('should save a model to the db', function (done) {
const article = new Article({
title: 'first blog',
author: 'john doe',
body: 'blah blah'
})
.save()
.then(function () { done() })
.catch(function (err) { done(err) });
});

Related

How to wait for result of service get?

I'm pretty sure the get function of the person service I use below returns a function, but my test doesn't seem to execute either branch, so it times out. Does that mean that get does not return a promise?
describe('person service', function () {
beforeEach(module('tournament'));
var person;
beforeEach(inject(function (_personService_) {
person = _personService_;
}));
it('should get person data', (done) => {
var expectedPerson = [
{ id: 2, last: 'Steigerwald', first: 'Michael' },
];
person.get(2).then(
(result) => {
expect(result).toEqual(expectedPerson);
done();
},
(reason) => {
console.log(reason.message);
done();
}
);
});
});

React - can't dispatch action in hook component

Using dispatch in useffect hook of functional component,
Below code shows error page like below;
Component:
import { GetParks } from "../../../redux/actions/survey_actions"
...
function BarcodeGenerator(props) {
const dispatch = useDispatch();
useEffect(() => {
dispatch(props.GetParks());
}, []);
actions:
export const GetParks = (Id) => async (dispatch, getState) => {
try {
const response = await axiosHelper.get("api/survey/GetParks", {
params: {
Id,
},
});
debugger;
response = response.data;
if (response.status !== ResponseStatus.SUCCESS) {
dispatch({
type: GET_PARKS,
payload: [1, 4555, 34],
});
}
} catch (error) {
catchCallback(error);
}
};
const _getParks = (data) => ({
type: GET_PARKS,
payload: data,
});
how does dispatch the action to reducer properly
Action must be a plain object, as it is described in the error description. E.g. it is ok to use dispatch directly as is:
if (*statement*) {
dispatch({
action: DO_SMTH,
payload: true
})
}
or to make the action creator returning the equal object if you want to make clean re-usable code:
if (*statement*) {
dispatch(doSmth(true));
}
function doSmth(toggle) {
return ({
action: DO_SMTH,
payload: toggle
})
}

Vuejs function with multiple data

I have two data table in vue app.
Cash [code, description,cash]
Upload [bank, id]
For my update function, i need to take [bank, id] from upload and [cash] from cash. i don't know how, can someone help please ? Thank you. This is my code
This is my vuejs
var app = new Vue({
el: '#app',
data: {
cash: {
codeentry: '',
description: '',
cash: '',
},
upload: {
bank: '',
id: '',
},
},
methods: {
updateBank: function () {
axios.put('/updatebank', this.upload, this.cash)
.then(response => {
if (response.data.etat) {
this.upload.id = response.data.etat.id
this.upload.bank = response.data.etat.bank
this.cash.cash = response.data.etat.cash
}
})
.catch(error => {
console.log('errors: ', error)
})
},
}
});
My route :
Route::put('/updatebank', 'CoinController#updateBank');
Controller :
public function updateBank(Request $request)
{
$coin = Coin::findOrFail($request->id);
$coin->bank = ($request->bank - $request->cash);
$coin->save();
}
When i execute my function and see the report. Only this.upload is token in consideration.
If you mean to have the two data in one object, you can make a new object from the two objects
Es6 Example:
const {bank,id} = this.upload;
const {cash} = this.cash;
const my_data = {
bank, id, cash
}
Older Js example
var my_data = {
cash: this.cash.cash,
bank: this.upload.bank,
id: this.upload.id,
}
Otherwise, if you want to have both in the request as separate objects then wrap around them {}
var my_data = {
upload: this.upload,
cash: this.cash
}
Finally:
axios.put('/updatebank', my_data)
...
Update: It appears you don't want to merge those objects as different sub-object so your updateBank method would be like so:
updateBank: function () {
const my_data = {
cash: this.cash.cash,
bank: this.upload.bank,
id: this.upload.id,
};
axios.put('/updatebank', my_data)
.then(response => {
if (response.data.etat) {
this.upload.id = response.data.etat.id
this.upload.bank = response.data.etat.bank
this.cash.cash = response.data.etat.cash
}
})
.catch(error => {
console.log('errors: ', error)
});
}
Just a side observation, are you sure the this in the response references your Vue object?

How can I test Observable.ajax (redux-observable)?

I have been playing with rxjs and redux-observable for the last few days and have been struggle to find a way to a test for Observable.ajax. I have the following epic which create a request to https://jsonplaceholder.typicode.com/,
export function testApiEpic (action$) {
return action$.ofType(REQUEST)
.switchMap(action =>
Observable.ajax({ url, method })
.map(data => successTestApi(data.response))
.catch(error => failureTestApi(error))
.takeUntil(action$.ofType(CLEAR))
)
}
where,
export const REQUEST = 'my-app/testApi/REQUEST'
export const SUCCESS = 'my-app/testApi/SUCCESS'
export const FAILURE = 'my-app/testApi/FAILURE'
export const CLEAR = 'my-app/testApi/CLEAR'
export function requestTestApi () {
return { type: REQUEST }
}
export function successTestApi (response) {
return { type: SUCCESS, response }
}
export function failureTestApi (error) {
return { type: FAILURE, error }
}
export function clearTestApi () {
return { type: CLEAR }
}
The code works fine when runs in browser but not when testing with Jest.
I have try,
1) Create a test based on https://redux-observable.js.org/docs/recipes/WritingTests.html. The store.getActions() returns only { type: REQUEST }.
const epicMiddleware = createEpicMiddleware(testApiEpic)
const mockStore = configureMockStore([epicMiddleware])
describe.only('fetchUserEpic', () => {
let store
beforeEach(() => {
store = mockStore()
})
afterEach(() => {
epicMiddleware.replaceEpic(testApiEpic)
})
it('returns a response, () => {
store.dispatch({ type: REQUEST })
expect(store.getActions()).toEqual([
{ type: REQUEST },
{ type: SUCCESS, response }
])
})
})
2) Create a test based on Redux-observable: failed jest test for epic. It returns with
Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
it('returns a response', (done) => {
const action$ = ActionsObservable.of({ type: REQUEST })
const store = { getState: () => {} }
testApiEpic(action$, store)
.toArray()
.subscribe(actions => {
expect(actions).to.deep.equal([
{ type: SUCCESS, response }
])
done()
})
})
Can someone point me out what is the correct way to test Observable.ajax ?
I would follow the second example, from StackOverflow. To make it work you'll need to make some minor adjustments. Instead of importing Observable.ajax in your epic file and using that reference directly, you need to use some form of dependency injection. One way is to provide it to the middleware when you create it.
import { ajax } from 'rxjs/observable/dom/ajax';
const epicMiddleware = createEpicMiddleware(rootEpic, {
dependencies: { ajax }
});
The object we passed as dependencies will be give to all epics as the third argument
export function testApiEpic (action$, store, { ajax }) {
return action$.ofType(REQUEST)
.switchMap(action =>
ajax({ url, method })
.map(data => successTestApi(data.response))
.catch(error => failureTestApi(error))
.takeUntil(action$.ofType(CLEAR))
);
}
Alternatively, you could not use the dependencies option of the middleware and instead just use default parameters:
export function testApiEpic (action$, store, ajax = Observable.ajax) {
return action$.ofType(REQUEST)
.switchMap(action =>
ajax({ url, method })
.map(data => successTestApi(data.response))
.catch(error => failureTestApi(error))
.takeUntil(action$.ofType(CLEAR))
);
}
Either one you choose, when we test the epic we can now call it directly and provide our own mock for it. Here are examples for success/error/cancel paths These are untested and might have issues, but should give you the general idea
it('handles success path', (done) => {
const action$ = ActionsObservable.of(requestTestApi())
const store = null; // not used by epic
const dependencies = {
ajax: (url, method) => Observable.of({ url, method })
};
testApiEpic(action$, store, dependencies)
.toArray()
.subscribe(actions => {
expect(actions).to.deep.equal([
successTestApi({ url: '/whatever-it-is', method: 'WHATEVERITIS' })
])
done();
});
});
it('handles error path', (done) => {
const action$ = ActionsObservable.of(requestTestApi())
const store = null; // not used by epic
const dependencies = {
ajax: (url, method) => Observable.throw({ url, method })
};
testApiEpic(action$, store, dependencies)
.toArray()
.subscribe(actions => {
expect(actions).to.deep.equal([
failureTestApi({ url: '/whatever-it-is', method: 'WHATEVERITIS' })
])
done();
});
});
it('supports cancellation', (done) => {
const action$ = ActionsObservable.of(requestTestApi(), clearTestApi())
const store = null; // not used by epic
const dependencies = {
ajax: (url, method) => Observable.of({ url, method }).delay(100)
};
const onNext = chai.spy();
testApiEpic(action$, store, dependencies)
.toArray()
.subscribe({
next: onNext,
complete: () => {
onNext.should.not.have.been.called();
done();
}
});
});
For the first way:
First, use isomorphic-fetch instead of Observable.ajax for nock support, like this
const fetchSomeData = (api: string, params: FetchDataParams) => {
const request = fetch(`${api}?${stringify(params)}`)
.then(res => res.json());
return Observable.from(request);
};
So my epic is:
const fetchDataEpic: Epic<GateAction, ImGateState> = action$ =>
action$
.ofType(FETCH_MODEL)
.mergeMap((action: FetchModel) =>
fetchDynamicData(action.url, action.params)
.map((payload: FetchedData) => fetchModelSucc(payload.data))
.catch(error => Observable.of(
fetchModelFail(error)
)));
Then, you may need an interval to decide when to finish the test.
describe("epics", () => {
let store: MockStore<{}>;
beforeEach(() => {
store = mockStore();
});
afterEach(() => {
nock.cleanAll();
epicMiddleware.replaceEpic(epic);
});
it("fetch data model succ", () => {
const payload = {
code: 0,
data: someData,
header: {},
msg: "ok"
};
const params = {
data1: 100,
data2: "4"
};
const mock = nock("https://test.com")
.get("/test")
.query(params)
.reply(200, payload);
const go = new Promise((resolve) => {
store.dispatch({
type: FETCH_MODEL,
url: "https://test.com/test",
params
});
let interval: number;
interval = window.setInterval(() => {
if (mock.isDone()) {
clearInterval(interval);
resolve(store.getActions());
}
}, 20);
});
return expect(go).resolves.toEqual([
{
type: FETCH_MODEL,
url: "https://test.com/assignment",
params
},
{
type: FETCH_MODEL_SUCC,
data: somData
}
]);
});
});
enjoy it :)

After closing the modal dialog refresh the base view

suggestion and code sample
I am new to Backbone marionette, I have a view ("JoinCommunityNonmemberWidgetview.js") which opens a modal dialog ("JoinCommunityDetailWidgetview.js").On closing of the dialog ( I want the view JoinCommunityNonmemberWidgetview.js") to be refreshed again by calling a specific function "submitsuccess" of the view JoinCommunityNonmemberWidgetview.js.
How can I achieve it.
The code for the modal is as below:
define(
[
"grads",
"views/base/forms/BaseFormLayout",
"models/MembershipRequestModel",
"require.text!templates/communitypagewidget/JoinCommunityWidgetDetailTemplate.htm",
],
function (grads, BaseFormLayout, MembershipRequestModel, JoinCommunityWidgetDetailTemplate) {
// Create custom bindings for edit form
var MemberDetailbindings = {
'[name="firstname"]': 'FirstName',
'[name="lastname"]': 'LastName',
'[name="organization"]': 'InstitutionName',
'[name="email"]': 'Email'
};
var Detailview = BaseFormLayout.extend({
formViewOptions: {
template: JoinCommunityWidgetDetailTemplate,
bindings: MemberDetailbindings,
labels: {
'InstitutionName': "Organization"
},
validation: {
'Email': function (value) {
var emailconf = this.attributes.conf;
if (value != emailconf) {
return 'Email message and Confirm email meassage should match';
}
}
}
},
editViewOptions: {
viewEvents: {
"after:render": function () {
var self = this;
var btn = this.$el.find('#buttonSubmit');
$j(btn).button();
}
}
},
showToolbar: false,
editMode: true,
events: {
"click [data-name='buttonSubmit']": "handleSubmitButton"
},
beforeInitialize: function (options) {
this.model = new MembershipRequestModel({ CommunityId: this.options.communityId, MembershipRequestStatusTypeId: 1, RequestDate: new Date() });
},
onRender: function () {
BaseFormLayout.prototype.onRender.call(this)
},
handleSubmitButton: function (event) {
this.hideErrors();
// this.model.set({ conf: 'conf' });
this.model.set({ conf: this.$el.find('#confirmemail-textbox').val() });
//this.form.currentView.save();
//console.log(this.form);
this.model.save({}, {
success: this.saveSuccess.bind(this),
error: this.saveError.bind(this),
wait: true
});
},
saveSuccess: function (model, response) {
var mesg = 'You have submitted a request to join this community.';
$j('<div>').html(mesg).dialog({
title: 'Success',
buttons: {
OK: function () {
$j(this).dialog('close');
}
}
});
grads.modal.close();
},
saveError: function (model, response) {
var msg = 'There was a problem. The request could not be processed.Please try again.';
$j('<div>').html(msg).dialog({
title: 'Error',
buttons: {
OK: function () {
$j(this).dialog('close');
}
}
});
}
});
return Detailview;
}
);
I would use Marionette's event framework.
Take a look at: https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.commands.md
Specifically, you need to:
1) Create a marionette application :
App = new Marionette.Application();
2) Use the application to set up event handlers
//Should be somewhere you can perform the logic you are after
App.commands.setHandler('refresh');
3) Fire a 'command' and let marionette route the event
App.execute('refresh');

Resources