I have been looking around option to create data seeders to add dummy data in my loopback 4 application. However I am not able to find any option in official documentation.
I have found couple of post but those refer to loopback 3, like:
Loopback: Creating a Seed Script
loopback-seed
Please point me out to documentation to do so.
EDIT:
As per suggestion I have created start.js file in scripts folder:
require('babel-register')({
presets: ['es2015']
})
module.exports = require('./seed.js')
And I have copied the script converting it to JavaScript mentioned in seed.js file. When I am running the script, I am getting error:
Cannot find module Models and Repositories
though I have typed correct path.
Actually, I'm doing it with Loopback directly like this (this is typescript):
import * as users from './users.json';
import * as Promise from 'bluebird';
import {Entity, DefaultCrudRepository} from '#loopback/repository';
import {MyApplication} from '../src/application';
import {User} from '../src/models';
import {UserRepository} from '../src/repositories';
const app = new MyApplication();
async function loadByModel<T extends Entity, ID>(items: T[], repository$: DefaultCrudRepository<T,ID>, type: { new(it: Partial<T>): T ;}){
console.log(type.toString());
let repository = await repository$;
await repository.deleteAll();
await Promise.map(items, async (item: T) => {
try{
return await repository.create((new type(item)));
} catch(e){
console.log(item);
}
}, {concurrency: 50});
}
async function load(){
await loadByModel(users, await app.getRepository(UserRepository), User);
}
app.boot().then(async () => {
await load();
console.log('done');
});
We used a separate library db-migrate to keep our migration and seed scripts out of our loopback codebase. Moreso, because db.migrate and db.update methods of juggler are not 100% accurate as mentioned in docs as well. LB4 Database Migrations
Related
I am migrating from vue 4.x to pinia, one of my file needs api key from store.
But I can't make it work even though I follow the Pinia documentation .
here is how I use pinia
// Repository.ts
import axios from "axios";
import { createPinia } from 'pinia'
import { useAuthStore } from '../stores/auth-store'
const pinia=createPinia();
let authStore = useAuthStore(pinia);
const baseURL = 'http://127.0.0.1:5678/res-api';
export default axios.create({
baseURL,
headers:{"Authorization":"Bearer " + authStore.getToken,
"Accept":"application/json"},
});
Expected result : to get the token from the store.
Console error
Uncaught ReferenceError: Cannot access 'useAuthStore' before initialization
at Repository.ts:6:17
Note: this working inside a component
You can solve this by importing the store inside the interceptors
import axios from "axios";
import { useAuthStore } from '../stores/auth-store';
const axiosClient = axios.create({
baseURL: 'http://127.0.0.1:5678/res-api'
});
axiosClient.interceptors.request.use((config) => {
const authStore = useAuthStore();
config.headers.Authorization = `Bearer ${authStore.getToken}`;
config.headers.Accept = "application/json";
return config
})
export default axiosClient;
This discussion may help you: Go to GitHub discussion
According to the documentation the pinia you created must go as a parameter to app.use. Not only that, but useAuthStore must be a store defined with defineStore and must not take a parameter. I'll leave a link that can help you, it doesn't create the store but you can browse the side menu to see several examples.
https://pinia.vuejs.org/core-concepts/outside-component-usage.html
Here is my sample project to demo the issue: https://codesandbox.io/s/infallible-shamir-sxrlb9.
The main cause here is that you cannot use Pinia's stores before passing it to the Vue's app. So given following code:
const pinia = createPinia(); // line 1
createApp(App).use(pinia).mount("#app"); // line 2
You cannot trigger any store in between line 1 and 2, but only after line 2.
In your code, likely you trigger an axios call before creating Vue app/add Pinia to Vue app. Please try to delay that axios call to trigger after Vue app's setup is complete.
I have a basic expo app with React Navigation.
In the top function Navigation I am initiating a useMutation call to an Apollo server like so:
import { callToServer, useMutation } from '../graphQL';
function Navigation() {
console.log("RENDERED");
const [call] = useMutation(callToServer);
call({ variables: { uid: 'xyz', phoneNumber: '123' } });
...
And my GraphQL settings is as follows:
import {
ApolloClient,
createHttpLink,
InMemoryCache,
useMutation,
} from '#apollo/client';
import { onError } from '#apollo/client/link/error';
import { callToServer } from './authAPI';
const cache = new InMemoryCache();
const httpLink = createHttpLink({
uri: `XXXXXXX/my-app/us-central1/graphql`,
});
const errorLink = onError(({ graphQLErrors, networkError }) => {
...
});
const client = new ApolloClient({
cache,
link: errorLink.concat(httpLink),
});
export {
useMutation,
callToServer,
};
export default client;
I want to clarify that I removed the httpLink from the client setting and I still get the two renders per call. I can see in the console that console.log("RENDERED") prints three times. Once when the app loads (normal) and twice after the useMutation call (not normal?)
What's going on here? Why is react re-renders twice per useMutation call? How do I avoid it?
UPDATE
I did further digging and it seems that useMutation does indeed cause the App to render twice - once when the request is sent, and once when it receives a response. I'm not sure I'm loving this default behavior which seems to have no way to disable. Why not let us decide if we want to re-render the App?
If someone has more insight to offer, Id love to hear about it.
Probably it's too late and maybe you've already found the solution, but still...
As I see you do not need data returned from mutation in the code above. In this case you can use useMutation option "ignoreResults" and set it to "true". So mutation will not update "data" property and will not cause any render.
I was following the ember Super Rental 3.15 tutorial, when I got to the working with data section, I updated the route index file with model hooks, the page stopped working. Also I am finding ember tutorials to be incomplete.
error says property of map is undefined
code in routes index.js file:
import Route from '#ember/routing/route';
const COMMUNITY_CATEGORIES = [
'Condo',
'Townhouse',
'Apartment'
];
export default class IndexRoute extends Route {
async model() {
let response = await fetch('/api/rentals.json');
let { data } = await response.json();
return data.map(model => {
let { attributes } = model;
let type;
if (COMMUNITY_CATEGORIES.includes(attributes.category)) {
type = 'Community';
} else {
type = 'Standalone';
}
return { type, ...attributes };
});
}
}
image if error message:
Your problem is that fetch('/api/rentals.json'); does not return the correct data. And so when you do let { data } = await response.json(); then data will be undefined and you can not do undefined.map.
So the code you posted is correct. The problem is somewhere else. You can check:
did you correctly add the rentals.json file? If you open http://localhost:4200/api/rentals.json do you see the data? So have you done this?
I see some error from mirage. The super-rentals tutorial does not use mirage. I can see this here (sidenote: that git repo is automatically created from the guides, so its always up to date). So this could be your problem. Depending how you configure mirage it will basically mock all your ajax requests. This means that fetch(... will no longer work then expected, mirage assumes you always want to use mocked data and you did not configure mirage correctly. You can try to remove mirage from your package.json, rerun npm install, restart the ember server and try it again.
I am trying to write unit testing for fastify application which also has custom fastify plugin.
Is there a way we can mock fastify plugin? I tried mocking using Jest and Sinon without much success.
Giorgios link to the file is broken, the mocks folder is now absent from the master branch. I dug the commit history to something around the time of his answer and I found a commit with the folder still there. I leave it here for those who will come in the future!
This is what works for me
Setup your plugin according to Fastify docs https://www.fastify.io/docs/latest/Reference/Plugins/
// establishDbConnection.ts
import fp from 'fastify-plugin';
import {FastifyInstance, FastifyPluginAsync} from 'fastify';
import { initDbConnection } from './myDbImpl';
const establishDbConnection: FastifyPluginAsync = async (fastify: FastifyInstance, opts) => {
fastify.addHook('onReady', async () => {
await initDbConnection()
});
};
export default fp(establishDbConnection);
mock the plugin with jest, make sure you wrap the mock function in fp() so that Fastify recognizes it as a plugin.
// myTest.ts
import fp from 'fastify-plugin';
const mockPlugin = fp(async () => jest.fn());
jest.mock('../../../fastifyPlugin/establishDbConnection', (() => {
return mockPlugin;
}));
Your question is a bit generic but if you are using Jest it must be enough for mocking a fastify plugin. You can take a look in this repo and more specifically this file . This is a mock file of fastify and you add the registered plugins and in the specific example addCustomHealthCheck and then in your test files you can just call jest.mock('fastify').
You do not give a specific use case and there are lot of reasons you might want to mock a plugin. The nature of the plugin to be mocked is important to giving a good answer. Because I don't know that specific information I will show how to mock a plugin that creates a decorator that stores data that can be retrieved with fastify.decorator-name. This is a common use case for plugins that connect to databases or store other widely needed variables.
In the below case, the goal is to test a query function that queries a db; a plugin stores the connection information via a fastify decorator. So, in order to unit test the query we specifically need to mock the client data for the connection.
First create an instance of fastify. Next, set up a mock to return the desired fake response. Then, instead of registering the component with fastify (which you could also do), simply decorate the required variables directly with mock information.
Here is the function to be tested. We need to mock a plugin for a database which creates a fastify decorator called db. Specifically, in the below case the function to be tested uses db.client:
const fastify = require("fastify")({ //this is here to gather logs
logger: {
level: "debug",
file: "./logs/combined.log"
}
});
const HOURS_FROM_LOADDATE = "12";
const allDataQuery = `
SELECT *
FROM todo_items
WHERE a."LOAD_DATE" > current_date - interval $1 hour
`;
const queryAll = async (db) => {
return await sendQuery(db, allDataQuery, [HOURS_FROM_LOADDATE]);
};
//send query to db and receive data
const sendQuery = async (db, query, queryParams) => {
var res = {};
try {
const todo_items = await db.client.any(query, queryParams);
res = todo_items;
} catch (e) {
fastify.log.error(e);
}
return res;
};
module.exports = {
queryByAsv
};
Following is the test case. We will mock db.client from the db plugin:
const { queryAll } = require("../src/query");
const any = {
any: jest.fn(() => {
return "mock response";
})
};
describe("should return db query", () => {
beforeAll(async () => {
// set up fastify for test instance
fastify_test = require("fastify")({
logger: {
level: "debug",
file: "./logs/combined.log",
prettyPrint: true
}
});
});
test("test Query All", async () => {
// mock client
const clientPromise = {
client: any
};
//
fastify_test.decorate("db", clientPromise);
const qAll = await queryAll(fastify_test.db);
expect(qAll).toEqual("mock response");
});
});
We are using the aurelia component testing as defined here (with jest): https://aurelia.io/docs/testing/components#testing-a-custom-element
The component we are testing has a transient dependency. We are creating a mock for this dependency but when we run the tests using au jest, the real one always gets injected by the DI container and never the mock.
Here is the Transient service:
import { transient } from "aurelia-framework";
#transient()
export class ItemService {
constructor() {
}
getItems(): void {
console.log('real item service');
}
}
Here is the 'Mock' service (we have also tried using jest mocks but we get the same result):
import { transient } from "aurelia-dependency-injection";
#transient()
export class MockItemService{
getItems():void {
console.log('mock item service');
}
}
Here is the component under test:
import {ItemService} from "../services/item-service";
import { autoinject } from "aurelia-dependency-injection";
#autoinject()
export class TestElement {
constructor(private _itemService: ItemService) {
}
attached(): void {
this._itemService.getItems();
}
}
Here is the spec file:
import {TestElement} from "../../src/resources/elements/test-element";
import {ComponentTester, StageComponent} from "aurelia-testing";
import {ItemService} from "../../src/resources/services/item-service";
import {MockItemService} from "./mock-item-service";
import {bootstrap} from "aurelia-bootstrapper";
describe('test element', () => {
let testElement;
const path: string = '../../src/resources/elements/test-element';
beforeEach(() => {
testElement = StageComponent.withResources(path).inView(`<test-element></test-element>`);
testElement.bootstrap(aurelia => {
aurelia.use.standardConfiguration();
aurelia.container.registerTransient(ItemService, MockItemService);
});
});
afterEach(() => {
testElement.dispose();
});
it('should call mock item service', async() => {
await testElement.create(bootstrap);
expect(testElement).toBeTruthy();
})
});
But every-time the test is run, the console logs out the real service and not the mock. I have traced this to the aurelia-dependency-injection.js in the Container.prototype.get function. The issue seems to be around this section of code:
var registration = aureliaMetadata.metadata.get(aureliaMetadata.metadata.registration, key);
if (registration === undefined) {
return this.parent._get(key);
}
The registration object seems to be a bit odd, if it was undefined, the code would work as the correct dependency is registered on the parent and it would get the mock dependency. However, it is not undefined therefore it registers the real service in the DI container on this line:
return registration.registerResolver(this, key, key).get(this, key);
The registration object looks like this:
registration = TransientRegistration {_key = undefined}
Is this a bug in aurelia or is there something wrong with what I am doing?
Many Thanks
p.s. GitHub repo here to replicate the issue: https://github.com/Magrangs/aurelia-transient-dependency-issue
p.p.s Forked the DI container repo and added a quick fix which would fix my particular issue but not sure what the knock on effects would be. If a member of the aurelia team could check, that would be good:
https://github.com/Magrangs/dependency-injection/commit/56c7d96a496e76f330a1fc3f9c4d62700b9ed596
After talking to Rob Eisenberg on the issue there is a workaround for this problem. Firstly remove the #transient decorator on the class and then in your app start (usually main.ts) register the class there as a transient.
See the thread here:
https://github.com/Magrangs/dependency-injection/commit/56c7d96a496e76f330a1fc3f9c4d62700b9ed596
I have also updated the repo posted above: https://github.com/Magrangs/aurelia-transient-dependency-issue
to include the fix.
Hopefully this will help any other devs facing the same issue.