RSpec + jasmine-node - ruby-on-rails

I was wondering if anyone has already solved a problem I am experiencing.
I am currently working on a project with processes split between Rails and a Nodejs process. I use RSpec for Rails based testing and jasmine-node for the Node counterpart.
My situation is that both the Rails and Node apps access the same database. My problem is that RSpec makes it trivial in setting a TEST database, seeding it with some values and running tests against these but jasmine-node has no such mechanism.
Instead, my jasmine-node database related tests have no mechanism to setup a TEST database so my jasmine-node tests instead rely on my DEVELOPMENT database. To me this is both wrong and bad as these tests are not repeatable.
Currently my jasmine-node tests are in a separate directory and outside of Rails' RSpec spec folder (and run via the jasmine-node command line). Recently I learnt that RSpec can drive jasmine client javascript tests. Does a similar mechanism exist to drive jasmine-node tests from RPsec?
Has anyone else encountered this problem? If so, I am very eager to hear how you've approached and tackled this problem.
My thanks and gratitude in advance.

My solution was to use an environment variable TEST to specify whether to use the test or development database. This example, which uses Sequelize, works with test and dev databases on both the local machine and Heroku.
var config = {}
if (typeof (process.env.DATABASE_URL) != 'undefined') {
var url = require('url');
var dbUrl;
if (process.env.TEST == 'true') {
dbUrl = url.parse(process.env.HEROKU_POSTGRESQL_NAVY_URL);
}
else {
dbUrl = url.parse(process.env.DATABASE_URL);
}
var authArr = dbUrl.auth.split(':');
config.database = dbUrl.path.substring(1);
config.username = authArr[0];
config.password = authArr[1];
config.host = dbUrl.hostname;
config.port = dbUrl.port;
config.dialect = 'postgres';
config.protocol = 'postgres';
config.importBatchSize = 1000;
}
else {
if (process.env.TEST == 'true') {
console.log('DB: test');
config.database = 'test';
config.username = 'postgres';
config.password = 'postgres';
config.host = '127.0.0.1';
config.port = 5432;
config.dialect = 'postgres';
config.protocol = 'tcp';
config.importBatchSize = 1000;
}
else {
console.log('DB: db');
config.database = 'db';
config.username = 'postgres';
config.password = 'postgres';
config.host = '127.0.0.1';
config.port = 5432;
config.dialect = 'postgres';
config.protocol = 'tcp';
config.importBatchSize = 1000;
}
}
config.logging = false;
//config.logging = console.log;
module.exports = config;
Then, each jasmine-node test that accesses the database does a require on a file containing the following bootstrapping code:
process.env['TEST'] = 'true'; // Use test database
var config = require('../config/config.js');
process.env['TEST'] = 'false'; // Stop using test database after this
var sequelizeSingleton = require("../classes/model.js");
sequelizeSingleton.setup(path.normalize(__dirname + '/../models'), config.database, config.username, config.password,
{ dialect: config.dialect, protocol: config.protocol, host: config.host, port: config.port, omitNull: true, logging: config.logging });

Related

Postman Embedded Environment Variables Not Being Evaluated

I am using Postman v6.1.4. I am using environment variables heavily. But it appears that pm.environment.get() is not evaluating embedded variables.
I have the following env vars defined in the environment:
addFavDest1:{"ownerId":"{{addFavDest1_ownerId}}","url":"{{addFavDest1_url}}",...}
...
addFavDestArray1:[{{addFavDest1}},{{addFavDest2}},{{addFavDest3}}]
The request body of my API contains:
{{addFavDestArray1}}
The request is sent successfully, with the data I expect, evaluating all of the embedded variables in my environment.
However, when I try to access that env var in my test script, the embedded variables are not being evaluated. For instance, the following:
var addFavDestArray1 = pm.environment.get('addFavDestArray1')
Returns [{{addFavDest1}},{{addFavDest2}},{{addFavDest3}}], with the variables not evaluated.
Is there some way to have the embedded variables evaluated in the environment?
So, in order to handle this situation, I created the following common function that I call from all my tests instead of pm.environment.get('var1') or environment['var1] or environment.var1.
/* funcGetAndEvalEnvVar */
var funcGetAndEvalEnvVar = (varName) => {
const EMBEDDED_VAR_REGEX = new RegExp(`{{\\w+}}`, 'g');
var varValue = environment[varName];
var evalVarValue = varValue;
var reMatch;
while (reMatch = EMBEDDED_VAR_REGEX.exec(varValue)) {
var embeddedVar = reMatch[0];
var embeddedVarName = embeddedVar.slice(2, -2);
if (environment.hasOwnProperty(embeddedVarName)) {
var embeddedVarValue = funcGetAndEvalEnvVar(embeddedVarName);
evalVarValue = evalVarValue.replace(new RegExp(embeddedVar, 'g'), embeddedVarValue);
}
}
return evalVarValue;
};

Rails Webpacker internal assets aren't proxied to action_controller.asset_host

I am using Rails 5.1 and Webpacker. It all works fine. I am using images inside my react components that are in /app/javascripts/images, and I import them fine into my components and all is well on development.
However - when I deploy, the internal images are now served directly from my site url (with their webpacker compiled paths, but the problem is I have set up my production environment to use an asset_host - so Rails is correctly prefixing all my other usual Rails image assets (including my react JS packs) - so they are all being served correctly from my asset_host.
JUST the internal images that are in /app/javascripts/images that I imported into my react components - they AREN'T being proxied through the asset_host. (it works fine in development - as I don't use an asset_host there).
How can I let webpacker know, that I need the images proxied through an asset_host on production?
You can add an environment argument "process.env.WEBPACKER_ASSET_HOST" to /config/webpack/production.js file.
process.env.NODE_ENV = process.env.NODE_ENV || 'production'
process.env.WEBPACKER_ASSET_HOST = process.env.WEBPACKER_ASSET_HOST || '/yourpath/'
const environment = require('./environment')
module.exports = environment.toWebpackConfig()
i am working in rails6. hope this can help someone
I managed top set up my config/webpack/environment.js file up like this:
const { environment } = require('#rails/webpacker')
const env = process.env.NODE_ENV || 'development'
const { resolve } = require('path')
const { safeLoad } = require('js-yaml')
const { readFileSync } = require('fs')
const filePath = resolve('config', 'webpacker.yml')
const appConfig = safeLoad(readFileSync(filePath), 'utf8')[env]
const config = appConfig
const removeOuterSlashes = string =>
string.replace(/^\/*/, '').replace(/\/*$/, '')
const formatPublicPath = (host = '', path = '') => {
let formattedHost = removeOuterSlashes(host)
if (formattedHost && !/^http/i.test(formattedHost)) {
formattedHost = `//${formattedHost}`
}
const formattedPath = removeOuterSlashes(path)
return `${formattedHost}/${formattedPath}/`
}
const fileLoader = environment.loaders.get('file')
fileLoader.use[0].options.publicPath = formatPublicPath(process.env.WEBPACKER_ASSET_HOST, config.public_output_path)
module.exports = environment
According to the following comment here: https://github.com/rails/webpacker/issues/1186#issuecomment-358110765

How to solve Rails environment difference? Works in staging but not in dev

I have dashboards that are in a backbone.js app in a larger Rails app. In staging and production (on heroku) the dashboards work fine.
However, in my local Pow dev environment I get the following error in the browser console when I try and view a specific dashboard:
Uncaught TypeError: Object #<Object> has no method 'merge'
After tracking that down a bit, here is what I came up with. The merge method being referred to in the error message is coming from the rendered /assets/templates/dashboard/details.js file. Here is the code with what the browser is calling the error at the start of line 5: helpers = this.merge...:
(function() {
this.HandlebarsTemplates || (this.HandlebarsTemplates = {});
this.HandlebarsTemplates["dashboard/details"] = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
this.compilerInfo = [4,'>= 1.0.0'];
helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
var buffer = "", stack1, functionType="function", escapeExpression=this.escapeExpression;
buffer += "<p>\n <b>Name:</b>\n <span class='editable' data-attribute-name='name'>";
if (stack1 = helpers.name) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
+ "</span>\n</p>\n<p>\n <b>Description:</b>\n <span class='editable' data-attribute-name='description'>";
if (stack1 = helpers.description) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.description; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
+ "</span>\n</p>\n<p>\n <button class='add_module'>Add module</button>\n</p>\n";
return buffer;
});
return this.HandlebarsTemplates["dashboard/details"];
}).call(this);
I think this is a Rails precompile or asset pipeline setup issue since it works fine in staging and production but fails in local development.
It sucks having to push any changes to heroku to test them. Any suggestions for solving this are appreciated.
It looks like this is resulting from my handlebars version being out of date. Thanks to the Thoughtbot guys for helping to track this down.
https://github.com/wycats/handlebars.js/issues/547

Render from controller is working fine in development but not in test

I have the following code in my grails app:
def list () {
def roles = principal.authorities*.authority
def page = roles.contains("ROLE_ADMIN")? "allcolors": "usercolors"
if (params.sort == "latest" || params.sort == null) {
logger.debug("came in if");
render view: page, model: [colorlist: colorService.colorList()]
}
else
render view: page, model: [colorlist: colorService.colorListForUser()]
}
When I run my application with grails run-app the above code works fine. However, when I deploy the war file created by grails test war target/myapp.war the above code does not work and errors with "Page not found" even though the debug statement came in if still gets printed.
I've tried to run this app in development with grails test run-app as well but even then the above does not work. Interestingly, when I run the app in prod mode (grails prod run-app) everything works fine as well. So it is certainly something to do with the test environment
Also, to ensure there aren't any data discrepancies I've changed dev test and prod to point at the same development database.
Could it be that my app has some special setting for test environment that I'm failing to see ...which would cause "render" to not work?
My environment looks like this:
environments {
development {
grails.logging.jul.usebridge = true
}
test {
grails.logging.jul.usebridge = true
}
production {
grails.logging.jul.usebridge = false
}
}
And DB config looks like this:
environments {
development {
dataSource {
dbCreate = "update" // one of 'create', 'create-drop', 'update', 'validate', ''
url = "jdbc:mysql://localhost/myapp?useUnicode=yes&zeroDateTimeBehavior=convertToNull&characterEncoding=UTF-8"
username = "root"
password = ""
}
hibernate {
}
}
test {
dataSource {
dbCreate =
url = "jdbc:mysql://localhost/myapp?useUnicode=yes&zeroDateTimeBehavior=convertToNull&characterEncoding=UTF-8"
username = "root"
password = ""
properties {
}
hibernate {
}
}
}
production {
dataSource {
dbCreate = "create-drop"
url = "jdbc:mysql://localhost/myapp?useUnicode=yes&zeroDateTimeBehavior=convertToNull&characterEncoding=UTF-8"
username = "root"
password = ""
}
}
}
How can I resolve this or troubleshoot it further??
run-app runs with the default "development" data source, which is not to be confused with the "test" environment. Check your Config.groovy (edit: and DataSource.groovy) and make sure you have test { } configured within your environments.
More info can be found in the grails documentation here:
http://www.grails.org/Environments

how can i dynamic update Datasource.groovy file

in a grails project, there will a file named DataSource.groovy. Such as follows:
dataSource {
pooled = true
driverClassName = "org.h2.Driver"
username = "sa"
password = ""
}
mongodb {
host = 127.0.0.1// adjust this according to your settings
port = 27017
databaseName = 'test'
username = 'user' // database user and password, if server requires authentication
password = 's3cret'
}
My question is that how can I set for example mongodb.host dynamically at run time.
If you have different MongoDB Hosts, you can set up different environments for development, test, and production using the environments closure in your DataSource.groovy.
In your example above, let's say that you are using localhost 127.0.0.1 for development and mongo-prodserver for production
environments {
development {
grails {
mongo {
host = "127.0.0.1"
port = 27017
username = "user"
password= "s3cret"
databaseName = "test"
}
}
}
production {
grails {
mongo {
host = "mongo-prodserver"
port = 27017
username = "user"
password= "s3cret"
databaseName = "prod"
}
}
}
...
}
Here is the link to Grails Doc on DataSources and Environments.

Resources