Add koa plugin to eggjs framework - javascript

I would like to add koa-validate to eggjs.
Code from koa-validate readme:
var koa = require('koa');
var app = koa();
var router = require('koa-router')();
require('koa-validate')(app);
app.use(require('koa-body')({multipart:true , formidable:{keepExtensions:true}}));
app.use(router.routes()).use(router.allowedMethods());
So I tried to add it as middleware as described in the eggjs docs:
// app/middleware/validate.js
const validate = require('koa-validate');
module.exports = (options, app) => {
validate(app);
return function session(ctx, next) {
return next();
}
}
But what I am actually looking for is to load the plugin 'on boot' and have the app object to add the validate plugin. Do you have any idea where I should place this?
thank you!

Okay, I solved it myself:
Add /app.js for life-cycle hooks and add the following code:
const validate = require('koa-validate');
class AppBootHook {
constructor(app) {
this.app = app;
validate(app);
}
}
module.exports = AppBootHook;
Instead of the documented this.checkQuery() the function is available as this.ctx.checkQuery.
Maybe this will help someone else.

Maybe not the answer but for egg js validating, there is already an official plugin there: https://github.com/eggjs/egg-validate
For the real answer: You can refer the example repo: https://github.com/Jeff-Tian/egg-useragent. This is a real world example that adds koa-useragent to eggjs framework. Core code is:
import {Application} from "egg"
import koaUserAgent from 'koa-useragent'
export default (app: Application) => {
app.use(koaUserAgent)
};

Related

Auto-indent javascript in vim, from one-liner to fully indented code

I am using vim to code, namely in javascript. I would love to be able to auto-indent javascript code. My main use case is being able to automatically jump from a one-liner javascript code to a fully indented pretty-printed code (just as https://beautifier.io/ would do).
Despite looking for help on google and SO, I was not able to find any auto-indent related question in the specific case where code to indent is a one-liner.
Sample input file :
import { BASE_URL } from "#/constants/config"; import { request } from "#/utils/request"; export const FOOTER_ENDPOINTS = { links: `${ BASE_URL} api/footer/links/`, } ; class Footer { async fetchLinks() { const { data } = await request({ url: FOOTER_ENDPOINTS.links, }); return data; } } export const FooterService = new Footer();
I am expecting the following output :
import { BASE_URL } from "#/constants/config";
import { request } from "#/utils/request";
export const FOOTER_ENDPOINTS = {
links: `${BASE_URL}api/footer/links/`,
};
class Footer {
async fetchLinks() {
const { data } = await request({
url: FOOTER_ENDPOINTS.links,
});
return data;
}
}
export const FooterService = new Footer();
So far i have unsuccessfully tried =G and gg=G commands, as well as :Autoformat from vim-autoformat plugin and pangloss/vim-javascript plugin.
Best hint I have is to use maksimr/vim-jsbeautify but the result is not as "pretty printed" as I would have expected. Maybe some editorconfig properties I do not know might help for adding line breaks and avoid imports being breaked when not too long ?
import {
BASE_URL
} from "#/constants/config";
import {
request
} from "#/utils/request";
export const FOOTER_ENDPOINTS = {
links: `${BASE_URL}api/footer/links/`,
};
class Footer {
async fetchLinks() {
const {
data
} = await request({
url: FOOTER_ENDPOINTS.links,
});
return data;
}
}
export const FooterService = new Footer();
BONUS : I would be amazing if the solution could also auto-indent dict-like entities such as javascript or json for instance.
Being the generalist text editor that it is, there is a limit to what Vim can do on its own with specific filetypes.
Out of the box, Vim is incapable of doing what you ask but it allows you to use external tools that do.
What you need to figure out is:
what external tool to use,
how to configure it to get the desired outcome,
how to integrate it with Vim.
js-beautify
The web app you mention uses js-beautify so, if you are happy with how the web app formats your code, then you should give js-beautify a try.
The first problem, here, is that the web app doesn't actually format your sample the way you claim it does. It outputs this:
import {
BASE_URL
} from "#/constants/config";
import {
request
} from "#/utils/request";
export const FOOTER_ENDPOINTS = {
links: `${ BASE_URL} api/footer/links/`,
};
class Footer {
async fetchLinks() {
const {
data
} = await request({
url: FOOTER_ENDPOINTS.links,
});
return data;
}
}
export const FooterService = new Footer();
which happens to be identical to what local js-beautify outputs by default.
If that web app is really able to format your code the way you want, then you must try various settings until you are satisfied and then move on to the configuration phase.
But there is a second problem: I just spent a few minutes playing with the settings and I'm afraid I have to point out that this statement:
just as https://beautifier.io/ would do
is patently false. The web app can't do your ideal formatting and the underlying js-beautify is very likely to be similarly limited.
So you are back to step #1: figuring out what external tool to useā€¦ which is outside of the scope of this site.

How to correctly export and import functions for cypress plugin index.ts?

I am developing plugin/index.ts file where I place async functions eg. clearing the database or uploading files to the app, but it starts to grow and I think about a way to keep it clean and structured.
In this video I see that there is a way to store functions in separate files and then export them using module.exports = { function } and then in the index.ts just import them using require.
But I can't have it working for my case.
This is a simplistic form of my plugins/index.ts file:
const uploadDocument = require('./documents');
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
on('task', {
clearDatabase: clearDatabase,
uploadDocument: uploadDocument,
});
async function clearDatabase() { ... }
}
I decided to move the code of function uploadDocument to the plugins/documents.ts file:
and this is how the file plugins/documents.ts looks like:
imports...
async function uploadDocument(fileName: string) { ... }
module.exports = { uploadDocument }
And when I run the test with a task this way:
cy.task("uploadDocument", 'Very_light_file.pdf')
I get this error in Cypress:
It looks like the problem is with your module.exports and the import.
Try this,
// document.ts
export async function uploadDocument(fileName: string) { ... }
// module.exports = { uploadDocument }
// plugins/index.ts
import { uploadDocument } from './documents'
From the post, I can tell TS is mixed JS there. The example is in JS, you're using TS, so there is no module.exports.
Try a pure JS version, then later convert it to TS.
If you look at cypress-io/cypress-realworld-app/blob/develop/cypress/plugins/index.ts you can see they change module.exports to:
// cypress/plugins/index.ts
export default (on, config) => {
config.env.defaultPassword = process.env.SEED_DEFAULT_USER_PASSWORD;
config.env.paginationPageSize = process.env.PAGINATION_PAGE_SIZE;
// Auth0
//
//
}

Fetch API can't find controller in asp .net core web api application

I'm attempting to use fetch api to load data from my asp .net core web api application to my react component. But I'm very confused that when I use the example await fetch('weatherforecast') in FetchData component to call WeatherForecastController. It works. I did a debugging in the example code, the function in WeatherForecastController is well reached, but if I use this idea in my project, it does not work, my function in debugging is not reached. Could someone explain the usage of fetch api in my case?
The controller class
[ApiController]
[Route("[controller]")]
public class HelloController : ControllerBase
{
[HttpGet]
public IEnumerable<T> Get()
{
//do something
}
}
My react component
const response = await fetch('Hello');
In program.cs (I'm using .net 6)
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddJsonFile("appsettings.json")
.Build();
builder.Services.AddDbContext<T>(options =>
options.UseSqlServer(configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddControllers();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new() { Title = "MY API", Version = "v1" });
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (builder.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "MY APP v1"));
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.UseRouting();
app.MapControllers();
app.Run();
I found something interesting in setupProxy
const { createProxyMiddleware } = require('http-proxy-middleware');
const context = [
'/weatherforecast',
'/controllerName1',
'/controllerName2',
];
module.exports = function (app) {
const appProxy = createProxyMiddleware(context, {
target: 'https://localhost:5001',
secure: false
});
app.use(appProxy);
};
The default weatherforecast controller works, de route is correct via debugging. But if I try it in another controller, it does not work. Can someone explain it pls?
Can you check Startup.cs? May be you have route prefix setup there. like api. So in that case your url would be /api/hello
Or configure swashbuckle that will tell exact route and also give you option to try your API

Taking screenshot in different route in angular using protractor

I am new to testing using protractor so for testing I have to take screenshots in an angular application for all the different routes in my app. I tried to do it on a small dummy angular app, so I cloned the Tour of heroes repo it has dashboard and Heroes route. I wrote the following code in app.po.ts :
import { browser, element, by } from 'protractor';
export class BlankPage {
navigateTo() {
return browser.get('/heroes');
}
getParagraphText() {
return element(by.tagName('h2')).getText();
}
}
and in app.e2e-spec.ts
import { BlankPage } from './app.po';
import {browser,by,element} from 'protractor';
import { protractor } from 'protractor';
import {createWriteStream} from 'fs' ;
describe('blank App', () => {
let page: BlankPage;
beforeEach(() => {
page = new BlankPage();
});
it('should display message saying app works', () => {
page.navigateTo();
expect(page.getParagraphText()).toEqual('My Heroes');
browser.takeScreenshot().then((png) =>{
var stream = createWriteStream("heroes.png"); /** change the png file name */
stream.write(new Buffer(png, 'base64'));
stream.end;
});
});
});
The idea was to navigate to heroes route and capture the screenshot. I got the screenshot but
Is there a way I can automate the task of going to all the routes and take screenshots ? In my actual website there are a lot of routes
I think the better solution for you is to add some reporter that will do everything for you, like taking screenshots after each test or after each failed tests and e.t.c.
Take a look at some reporters:
allure-jasmine - Highly recommended.
protractor-jasmine2-screenshot-reporter
protractor-jasmine2-html-reporter
protractor-html-reporter-2
protractor-html-screenshot-reporter
protractor-beautiful-reporter
But If you don't want to add any extra libraries to your project you can just put the browser.takeScreenshot() function to the afterEach function to take a screenshot after each test (it).
For instance:
describe('blank App', () => {
let page: BlankPage;
beforeEach(() => {
page = new BlankPage();
});
afterEach(() =>
browser.takeScreenshot().then((png) =>{
var stream = createWriteStream("heroes.png"); /** change the png file name */
stream.write(new Buffer(png, 'base64'));
stream.end;
});
});
it('should display message saying app works', () => {
page.navigateTo();
expect(page.getParagraphText()).toEqual('My Heroes');
});
});
I think the best approach for you would be the have a list of all the routes in your application and create a datadriven test to iterate over each one.
You would need a generic navigation function which could get to each page e.g navigateTo(routeName). That code would look something like this.
var routes = [
'homepage',
'myheroes',
'mainpage',
'heroprofile'
]
describe('blank App', () => {
for (let i = 0; i < routes.length; i++) {
it('should display message saying app works', () => {
navigateTo(routes[i]);
browser.takeScreenshot().then((png) => {
var stream = createWriteStream(routes[i] + ".png"); /** change the png file name */
stream.write(new Buffer(png, 'base64'));
stream.end;
});
});
}
});
protractor-image-compare
Really though I would recommend you use the npm package protractor-image-comparison. I've worked with this package and it does make visual validation very straightforward. It allows you to save new baseline images (golden images as you call them) if they are absent and compares them if they are present. The comparison are very sensitive to change but you can set how much of a difference you want to allow.
There would be no database required with this approach.
Note
Be aware also that different browsers take screenshots differently based. Chrome considers the "viewport" to be the visible portion of the browser but I believe in firefox you can screenshot the entire webpage at once.

How to stub ES6 node_modules when using import?

I am a bit confused while writing tests. My stack is mocha, chai and sinon + babel to transpile. And recently I've started to use ES6 imports and exports. It's working great so far, but I have trouble with mocking some dependencies. Here is my case:
service.js
import {v4} from 'uuid';
function doSomethingWithUuid() {
return v4();
}
export function doSomething() {
const newUuid = doSomethingWithUuid();
return newUuid;
}
service.test.js
import {doSomething} from './service';
describe('service', () => {
it('should doSomething' () => {
// how to test the return of doSomething ?
// I need to stub v4 but I don't know how...
});
});
Things I've considered: sinon.stub, but I have not managed to make it work. Trying to import all uuid with import * as uuid from 'uuid'. But within my service.js, it's still
the original function which is called...
Plus as imports are supposed to be read-only, once it'll be native, this solution wouldn't work...
The only interesting thing I found on the net was this solution, to add a function in my service in order to let the outside world to override my dependencies.
(see https://railsware.com/blog/2017/01/10/mocking-es6-module-import-without-dependency-injection/).
import * as originalUuid from 'uuid';
let {v4} = originalUuid;
export function mock(mockUuid) {
({v4} = mockUuid || originalUuid);
}
This is ok to write this little boilerplate code, but it troubles me to add it in my code... I would prefer to write boilerplate in my test or some config. Plus, I don't want to
have an IoC container, I want to keep my functions as little as possible and stay as fonctional as I can...
Do you have any ideas? :)
You should be able to use a module like proxyquire for this. This is not tested code, but it would go something like the following:
const proxyquire = require('proxyquire');
const uuidStub = { };
const service = proxyquire('./service', { uuid: uuidStub });
uuidStub.v4 = () => 'a4ead786-95a2-11e7-843f-28cfe94b0175';
describe('service', () => {
it('should doSomething' () => {
// doSomething() should now return the hard-coded UUID
// for predictable testing.
});
});

Categories