How do I access ENV from config/environment in an addon? - ember.js

This is a question that was asked by #dbendaou over on the Ember Discord
What is the best way to access ENV from config/envirnoment in an addon?
I was thinking about getOwner(this).lookup('config:environment') but it doesn't work
neither does import ENV from '../config/environment'; 😅

From addons, specifically, since your context doesn't define the environment, you need a slightly different API:
import { getOwner } from '#ember/application';
// ....
export default class MyAddonComponent extends Component {
get env() {
getOwner(this).resolveRegistration('config:environment')
}
}
import ENV from '../config/environment' is an alias for import ENV from '<app-name>/config/environment'; which, addons can't know what the <app-name> is.
Maybe related, because this has come up a number of times in the discord, is that this would also be how you get access to environment variables at runtime.
environment.js is a build-time file, so it has access to the node environment your app builds in and it outputs a JSON object for your app to consume.
For example:
// <your-app>/config/environment.js
const MY_ENV_VAR = process.env;
module.exports = function (environment) {
let ENV = {
// ...
MY_ENV_VAR,
};
return ENV;
}
Then, your addon can access MY_ENV_VAR via resolveRegistration. and apps can access it via the import.
Apps:
import ENV from '<app-name>/config/environment'
// ...
ENV.MY_ENV_VAR
Addons:
getOwner(this).resolveRegistration('config:environment').MY_ENV_VAR;

Related

UI Kitten & React Native Web no custom mapping

I am having an issue trying to load the most basic custom mapping in React Native Web. The custom styles are loading just fine in the App, but not Web. Using the latest version with the babel loader hack as proposed here. I am using the default mapping as proposed in the UI Kitten docs for v5.x
My code looks like this:
import * as eva from '#eva-design/eva'
import * as mapping from '../styles/mapping.json'
import { myTheme } from '../styles/light-theme'
export default function App(): React.ReactElement {
return <>
<ApplicationProvider {...eva} theme={myTheme} customMapping={mapping}>
...
</ApplicationProvider>
</>
}
I tried replicating with a blank repo and it was working fine, so one line at a time I figured out that my import was not correct (not readable by babel?).
Instead of:
import * as mapping from '../styles/mapping.json'
Should be:
import {default as mapping} from '../styles/mapping.json'
The correct way is suggested in the UIKitten docs, so I don't think it will happen to many, but may help others as it's not an obvious thing if someone is working with the App emulator for the most time and not checking the Web until later.
This is the way I use the custom mapping with ts file: custom-mapping.ts
export const customMapping: any = {
components: {
CircleButton: {
meta:{...},
appearances: {...}
}
}
}
and import it like this:
...
import {customMapping} from '../custom-mapping';
<ApplicationProvider
...
customMapping={{...eva.mapping, ...customMapping}}
>
{children}
</ApplicationProvider>

How to inject app.context into Loopback 4 controller

I cannot find any suitable example on how to inject an app.context object into a Loopback 4 controller being in a separate file
This inline example from the documentation works fine
import {inject} from '#loopback/context';
import {Application} from '#loopback/core';
const app = new Application();
app.bind('defaultName').to('John');
export class HelloController {
constructor(#inject('defaultName') private name: string) {}
greet(name?: string) {
return `Hello ${name || this.name}`;
}
}
but I cannot find a way to obtain the same having my controller in a separate file.
I am trying to do something like this:
export class PingController {
constructor(#inject(app.name) private name: string)
app.name being a simple binding in my app-context.
Solution was quite simple.
Since all context values on app level is available throughout the application, no reference to app is required.
I just needed to replace (app.name) with ('name') in the constructor injection.

How to mock global Vue.js variable in JEST test

I have a global property/variable with my app urls:
Vue.prototype.$apiUrls = {
root: 'http://localhost:8080/',
api: 'api/v1/'
// etc.
}
I use it inside my components as axios request:
axios.get(`${this.$apiUrls.root}${this.$apiUrls.api}/users/`)
Now I want to test my component's code, I've mocked axios already, but still I receive an error:
TypeError: Cannot read property '$apiUrls' of undefined
I've tried to define/mock this property inside each test and/or in JEST's setup file, like e.g.
global.$apiUrls = {...}
// or
Vue.prototype.$apiUrls = {...}
// or
Object.defineProperties(Vue.prototype, {$apiUrls: {...}})
I've also tried mocking it to window or this (yeah, thats silly), but with no success - I still receive that error - please help.
There is two ways to achieve this. One is using the Config option, as mentioned by #Aldarund. You can read about it here.
If you are using Jest, I recommend doing this in the jest.init.js file:
import { config } from '#vue/test-utils'
config.mocks['$apiUrls'] = {
'some/endpoint'
}
Then add this to the jest section of your package.json:
"setupFiles": [
"<rootDir>/jest.init.js"
]
Now it is globally mocked. If you want to do this on a per test basis, you can use the mocks mounting option:
const wrapper = shallowMount(Foo, {
mocks: {
$apiUrls: 'some/endpoint'
}
})
Hopefully this helps!
If you are interested I am compiling a collection of simple guides on how to test Vue components here. It's under development, but feel free to ask make an issue if you need help with other related things to testing Vue components.
I don't think the answers above work anymore (in 2020).
Here's what worked for me:
For vue-test-utils 1.x.x (Vue 2)
Create a new file, name it eg. jest.init.js
Give it the following content:
import { config } from "#vue/test-utils";
config.mocks["yourGlobalProperty"] = label => label; //you can replace it with your own mock
Add this to your jest.config.js (actually write "rootDir", don't replace anything with a real path)
module.exports = {
setupFiles: ["<rootDir>/jest.init.js"]
}
These files will be only ran before jest runs unit tests.
Note that I'm importing {config}, not the default export. I don't know why the default didn't work for me. Even the documentation for vue test utils doesn't import the default export anymore
Also make sure you're not trying to import from the old vue-test-utils package. (The new one is #vue/test-utils)
For #vue/test-utils 2.x.x (vue-test-utils-next) (Vue 3)
Follow steps like for 1.x.x above, but in step two, do this instead:
import { config } from "#vue/test-utils"; //2.0.0-beta.5
config.global.mocks = {
yourGlobalProperty: label => label
};
You can do it with vue-test-utils beta 15 and later.
Here docs
And some example would be:
import VueTestUtils from '#vue/test-utils'
VueTestUtils.config.mocks['$apiUrls'] = {
...
}

Jest globalSetup option not working

I'm trying to make a function called loadFixtures available to all Jest tests.
I have the following line within the jest config object inside package.json:
"globalSetup": "<rootDir>/src/test/js/config/setup-globals.js"
setup-globals.js contains:
module.exports = function() {
function loadFixtures(filename) {
console.info('loadFixtures is working');
}
}
Within my tests I have, for example:
beforeEach(() => {
loadFixtures('tooltip-fixture.html');
});
However when I run Jest I get the following for each test:
ReferenceError: loadFixtures is not defined
I verified that the setup-globals.js file is definitely being found and loaded in by Jest before the tests execute.
Can anyone assist in identifying where I've gone wrong here? I've spent pretty much an entire day trying to debug without luck.
You should be using setupFiles and not globalSetup.
// jest config
"setupFiles": [
"<rootDir>/src/test/js/config/setup-globals.js"
]
then src/test/js/config/setup-globals.js:
global.loadFixtures(filename) {
console.info('loadFixtures is working');
}
references: https://medium.com/#justintulk/how-to-mock-an-external-library-in-jest-140ac7b210c2
If you bootstrapped your application using npx create-react-app (CRA), you do not need to add the setupFiles key under your jest key in the package.json file (CRA prevents overriding that key).
what you simply need to do is to add the file setupTests.js in the root of your SRC folder, and populate it with the snippet below:
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({
adapter: new Adapter(),
});
remember you must have earlier installed the right versions of enzyme and enzyme-adapter-react
CRA has been wired to automatically load the setupTests.js file in the src folder if it exists. Hence after adding these, you can then go over to your test and do import {shallow} from enzyme without triggering an error.
if you are not using Create-react-app, all you need to do, in addition to adding the file above to your src folder is to add the key setupFiles into the jest key in your package.json. it should look like this:
"jest": {
"setupFiles": ['<rootDir>/src/setupTests.js'],
}
and you are good to go.
Cheers!
You're defining a function in a different scope. How about you create a separate module and import it directly in your test files. Or if you really want to define it in the global scope, try using the following code in your setup-globals.js file.
module.exports = function() {
global.loadFixtures = function(filename) {
console.info('loadFixtures is working');
}
}

TypeScript UnitTests on Module

I want to run unit tests in typescript. I have a simple folder structure where directory app contains an app.ts like following
export module app {
export class Config {
testMe() {
return "Hallo";
}
}
}
The unit tests that lies in directory test:
import app = require('../app/conf');
import * as chai from 'chai';
var config = new app.app.Config();
chai.expect(config.testMe()).to.equals("Hallo");
As TypeScripts documentation states in http://www.typescriptlang.org/Handbook#modules-pitfalls-of-modules when TypeScript code is used as an external module it does not make sense to use the module concept at all.
As you can see app.app.Config is not a very elegant way.
I can only run my unit tests on compiled TypeScript code. So I can only use modules if I don't care about unit tests or is there a simpler way?
Have app.ts:
export class Config {
testMe() {
return "Hallo";
}
}
and test.ts:
import app = require('../app/conf');
import * as chai from 'chai';
var config = new app.Config();
chai.expect(config.testMe()).to.equals("Hallo");
And if your original code worked, so will this. No more app.app and no more needless internal modules.