How do I set the baseURL that is used in useFetch composable globally (maybe nuxt.config.ts) so that I wouldn't have to define it in every useFetch.
You can define the baseURL in your nuxt.config.js|ts like this:
import { defineNuxtConfig } from 'nuxt'
export default defineNuxtConfig({
// ...
runtimeConfig: {
public: {
baseURL: process.env.BASE_URL || 'https://api.example.com/',
},
},
// ...
(or use a fixed value or only the environment variable - as you like)
And add this composable:
// /composables/useMyFetch.js
export const useMyFetch = (request, opts) => {
const config = useRuntimeConfig()
return useFetch(request, { baseURL: config.public.baseURL, ...opts })
}
If you want to have the full blown version with types it's a bit longer:
// /composables/useMyFetch.ts
import { UseFetchOptions } from '#app'
import { NitroFetchRequest } from 'nitropack'
import { KeyOfRes } from 'nuxt/dist/app/composables/asyncData'
export function useMyFetch<T>(
request: NitroFetchRequest,
opts?:
| UseFetchOptions<
T extends void ? unknown : T,
(res: T extends void ? unknown : T) => T extends void ? unknown : T,
KeyOfRes<
(res: T extends void ? unknown : T) => T extends void ? unknown : T
>
>
| undefined
) {
const config = useRuntimeConfig()
return useFetch<T>(request, {
baseURL: config.public.baseURL,
...opts,
})
}
You can then use useMyFetch as replacement for useFetch - but with baseURL being set :-)
The following composable could be set
/composables/useJsonP.ts
export const useJsonP = async (path) => {
return await useFetch(() => `https://jsonplaceholder.typicode.com/${path}`)
}
And you could call this in your view
<script setup>
const jsonP = await useJsonP('todos/1')
</script>
<template>
<div>
<pre>{{ jsonP.data }}</pre>
</div>
</template>
That way, no need to define it somewhere and hack somehow the configuration. You do have a simple way of defining reusable pieces of code, that are directly imported into your components/views thanks to the DX of Nuxt.
For anyone still looking for the answer to the original question you can do this in nuxt.config with runtimeConfig and env variables. You can of course replace the env variables with a hard-coded values if you prefer.
In your nuxt.config.js/ts
runtimeConfig: {
SOME_SECRET_KEY: process.env.SOME_SECRET_KEY,
public: {
SOME_API_KEY: process.env.SOME_API_KEY,
},
},
Then in someComposable.js:
const config = useRuntimeConfig();
You can then access your variables as eg config.public.SOME_API_KEY
Hope that helps. More info here: https://v3.nuxtjs.org/guide/features/runtime-config
You can also involve .env like this
in .env
NUXT_PUBLIC_BASE_URL = https://www.someapi.com
in nuxt.config.js/ts
runtimeConfig: {
public: {
BASE_URL: 'some fallback value',
},
},
as it said in the document BASE_URL will be replaced by NUXT_PUBLIC_BASE_URL automatically
( no need to use process.env.NUXT_PUBLIC_BASE_URL )
and in composable you can use
const config = useRuntimeConfig();
console.log('base url is' , config.baseUrl)
Lit docs refer to Web Test Runner as testing. It navigates to this example page.
I tried testing MyElement, which has only one <p>.
import { LitElement, html } from "lit";
import { customElement } from "lit/decorators.js";
#customElement("my-element")
export class MyElement extends LitElement {
render() {
return html`<p>Hello, World.</p>`;
}
}
declare global {
interface HTMLElementTagNameMap {
"my-element": MyElement;
}
}
When testing by open-wc, the element's shadowDom did not have <p> in descendant.
import { expect, fixture, html } from "#open-wc/testing";
import { MyElement } from "../src/MyElement";
it("get shadowDom", async () => {
const el: MyElement = await fixture(html`<my-element></my-element>`);
expect(el).shadowDom.to.be.not.null; // passed
expect(el).shadowDom.to.have.descendant("p"); // failed
});
Does it need more setup to test Lit elements with open-wc?
web-test-runner.config.js is:
import { esbuildPlugin } from '#web/dev-server-esbuild';
export default {
files: ['test/*.test.ts'],
plugins: [esbuildPlugin({ ts: true })],
};
Try shadowRoot instead of shadowDom:
it("get shadowDom", async () => {
const el = await fixture(
html` <my-element></my-element>`
);
const descendant = el.shadowRoot!.querySelector("p")!;
expect(descendant).to.be.not.null;
});
I had similar issue. In my case shadowRoot was "null". To have shadowRoot content I had to import my web component like that:
import './myWebcomponent';
I am trying to make Jasmine & Karma framework into the current angular application running in ver 8.2. But i am coming across this weird error inside the Karma test running window:
Failed: Unexpected value 'DecoratorFactory' imported by the module 'DynamicTestModule'. Please add a #NgModule annotation.
What is the problem?
My componenent.spec.ts looks like this:
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { HomeComponent } from './home.component';
import { NO_ERRORS_SCHEMA} from '#angular/core';
import {RouterTestingModule} from '#angular/router/testing';
import {HttpClientTestingModule} from '#angular/common/http/testing';
import { MsalService } from '#azure/msal-angular';
import { Store } from '#ngrx/store';
import { Pipe } from '#angular/core';
describe('HomeComponent', () => {
let component: HomeComponent;
let fixture: ComponentFixture<HomeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule, HttpClientTestingModule, Pipe]
,declarations: [HomeComponent]
,schemas:[NO_ERRORS_SCHEMA]
,providers: [
{provide: MsalService, useFactory: '' },
{provide: Store, useFactory: '' }
]
})
.compileComponents();
}));
it('should have header text', async(() => {
const fixture = TestBed.createComponent(HomeComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
//expect(compiled.querySelector('.header-txt').textContent).toContain('Tax');
}));
});
I found the cause :-
export class MockStore<T> {
private state: BehaviorSubject<T> = new BehaviorSubject(undefined);
setState(data: T) { this.state.next(data); }
select(selector?: any): Observable<T> {
return this.state.asObservable();
}
pipe() {}
dispatch(action: any) { }
}
========================================================================
TestBed.configureTestingModule({
{provide: Store, useFactory: 'MockStore' }
..............
The useFactory property must be some custom class name. Now i mocked the store class.
EDIT : Obviously this is outdated, now you provide your guard at the providers array in an NgModule. Watch other answers or official documentation for more information.
bootstrapping on a component is outdated
provideRouter() is outdated as well
I'm trying to setup Authentication in my project, using a login and AuthGuard from the Angular2 guide : https://angular.io/docs/ts/latest/guide/router.html
I'm using the release : "#angular/router": "3.0.0-beta.1".
I'll try to explain as much as possible, feel free to tell me if you need more details.
I have my main.ts file which boostraps the app with the following code :
bootstrap(MasterComponent, [
APP_ROUTER_PROVIDERS,
MenuService
])
.catch(err => console.error(err));
I load the MasterComponent, which loads a Header containing buttons that allow me to navigate through my app and it also contains my main for now.
I'm following the guide to make my app work the same way, with the following app.routes.ts :
export const routes: RouterConfig = [
...LoginRoutes,
...MasterRoutes
];
export const APP_ROUTER_PROVIDERS = [
provideRouter(routes),
AUTH_PROVIDERS
];
And the login.routes.ts from the guide, which defines my AuthGuard :
export const LoginRoutes = [
{ path: 'login', component: LoginComponent }
];
export const AUTH_PROVIDERS = [AuthGuard, AuthService];
my Master component has its own route definition, which also contains the guard I'm trying to setup. master.routes.ts :
export const MasterRoutes : RouterConfig = [
{ path: '', redirectTo: '/accueil', pathMatch: 'full' },
{
path: 'accueil',
component: AccueilComponent
},
{ path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] },
];
And I'm using the same files as the guide, which are auth.guard.ts, auth.service.ts, login.component.ts and login.routes.ts.
In my header.component.ts file, when I try to access any routes, it's working just fine, but when I try to access the guarded path (/dashboard), I get the No provider for AuthGuard! error.
I saw the recent post with the same issue as mine (NoProviderError using CanActivate in Angular 2), but to me the guard is bootstraped correctly up to the main.ts file, so my router should know which routes should be provided with the AuthGuard right ?
Any help or advice would be greatly appreciated.
Thanks !
I had this same issue after going through the Route Guards section of Routing and Authorization tutorial on the Angular website https://angular.io/docs/ts/latest/guide/router.html, it is section 5.
I am adding AuthGuard to one of my main routes and not to child routes like the tutorial shows.
I fixed it by added AuthGuard to my list of providers in my app.module.ts file, so that file now looks like this:
import { AppComponent } from './app.component';
import {AppRoutingModule} from './app-routing.module';
import {AuthGuard} from './auth-gaurd.service';
import { AnotherPageComponent } from './another-page/another-page.component';
import { LoginPageComponent } from './login-page/login-page.component';
#NgModule({
imports: [
BrowserModule,
FormsModule,
JsonpModule,
AppRoutingModule,
HttpModule
],
declarations: [
AppComponent,
LoginPageComponent,
AnotherPageComponent
],
providers: [AuthGuard],
bootstrap: [AppComponent]
})
export class AppModule { }
I have gone back through the tutorial and in their app.module.ts file, they do not add AuthGuard to the providers, not sure why.
Try to add
#Injectable({
providedIn: 'root'
})
no need to add to module provider.
Also, don't fall into the trap of using a literal for the guard class inside your routing configuration, just because some blog articles do:
{ path: 'whatever', component: WhatEverComponent, canActivate: ['WhatEverGuard'] }
is not going to work (No provider for...), instead, use the class directly:
{ path: 'whatever', component: WhatEverComponent, canActivate: [WhatEverGuard] }
Another hint, when lazy loading components, the guard is applied in the routing configuration of the parent component, not in the routing configuration of the lazy loaded component.
For those who still have this error - don't forget to include your AuthGuard service or class to main bootstrap function.
And don't forget to import this service before bootstrap runs.
import { bootstrap } from '#angular/platform-browser-dynamic';
import { AppComponent } from './app.component';
import { AuthGuard } from './shared/auth.service';
bootstrap(AppComponent, [
appRouterProviders,
AuthGuard
]);
Angular 2 team did not mention this in main router docs, and it took couple of hours for me to figure it out.
The answer is further down in the tutorial. See the file listings in the "Add the LoginComponent" topic under the "Component-less route:..." section in "Milestone 5: Route Guards". It shows AuthGuard and AuthService being imported and added to the providers array in login-routing.module.ts, and then that module being imported into app.module.ts.
login-routing.module.ts
...
import { AuthGuard } from './auth-guard.service';
import { AuthService } from './auth.service';
...
#NgModule({
...
providers: [
AuthGuard,
AuthService
]
})
export class LoginRoutingModule {}
app.module.ts
import { LoginRoutingModule } from './login-routing.module';
#NgModule({
imports: [
...
LoginRoutingModule,
...
],
...
providers: [
DialogService
],
...
Actually, it was only a typo in an import...
I was typing
import { AuthGuard } from './../Authentification/auth.guard';
instead of
import { AuthGuard } from './../authentification/auth.guard';
making it not working but at the same time not displaying me any error...
(sadface)
I encountered this issue when I was following a tutorial. I tried most of the answer here but not getting any success. Then I tried the silly way like putting the AuthGuard before the other services in the provider and it works.
// app.module.ts
..
providers: [
AuthGuard,
UserService,
ProjectService
]
Since you got the solution as it was due to syntax issue. I just wanted to share this info.
we need to provide the AuthGaudSerivce as provider in only that module that correspond to respective route. No need to provide in main module or root module as main module will automatically load all the given sub module.This helps in keeping the code modular and encapsulated.
for example, suppose we have below scenario
1. we have module m1
2. we have route m1r in module m1
3. route m1r has 2 route r1 and r2
4. we want to protect r1 using authGaurd
5. finally we have main module that is dependent on sub module m1
Below is just prototype, not the actual code for understanding purpose
//m1.ts
import {AuthGaurd} from './auth.gaurd.service'
import {m1r} from './m1r'
#NgModule(
imports: [m1r],
providers: [AuthGaurd]
)
export class m1{
}
//m1r.ts
import {AuthGaurd} from './auth.gaurd.service'
const authRoute = [
{path: '/r1', component: 'authComponent', canActivate: [AuthGaurd]},
{path: '/r2', component: 'other'}
]
export authRoute
//main.module.ts
import {m1} from ''
import {mainComponent} from ''
#NgModule({
imports: [m1],
bootstrap: [mainComponent]
})
export class MainModule{}
import { Injectable } from '#angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '#angular/router';
#Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if (localStorage.getItem('currentUser')) {
// logged in so return true
return true;
}
// not logged in so redirect to login page with the return url
this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }});
return false;
}
}
Importing both HttpModule and HttpClientModule helped me.
import { HttpClientModule } from '#angular/common/http';
import { HttpModule } from '#angular/http';
you can try import AuthGuard in provider of that module and then import it in the routing component-routing.module.ts file also
#NgModule({
providers: [
AuthGuard
],})
This happened to me when I had setup my Routes incorrectly:
WRONG
const routes: Routes =
[
{
path: 'my-path',
component: MyComponent,
resolve: { myList: MyListResolver, canActivate: [ AuthenticationGuard ] }
},
];
Note that in this case canActivate was accidentally made a part of the resolve object.
CORRECT
const routes: Routes =
[
{
path: 'my-path',
component: MyComponent,
resolve: { myList: MyListResolver },
canActivate: [ AuthenticationGuard ]
},
];
everyone. I try to test angular 2 application and got some interesting error when I try to test component with directives (and in those directive-components - router is included). Got error from Karma:
Error loading http://localhost:9876/angular2/router as "angular2/router" from D:built/application/breadcrumbs/breadcrumbs.component.js .
I don`t know what to do with this issue. Can anybody help me please?
There is my header component test (via jasmine and Karma):
import { beforeEach,
beforeEachProviders,
describe,
expect,
it,
inject,
injectAsync} from 'angular2/testing';
import {HeaderComponent} from './header.component';
import {BreadcrumbsComponent} from '../../breadcrumbs/breadcrumbs.component';
describe('HeaderComponent Tests', () => {
//let HeaderComponent: HeaderComponent;
beforeEachProviders(() => [HeaderComponent,
BreadcrumbsComponent,
ROUTER_PROVIDERS]);
it('Should contains title property - "Header"', inject([HeaderComponent],
(headerComponent: HeaderComponent) => {
expect(headerComponent.title).toBe('Header');
}));
});
There is header component that I try to test.
import {Component} from 'angular2/core';
import {HeaderDataInterface} from './header.component.interfaces';
import {BreadcrumbsComponent} from '../../breadcrumbs/breadcrumbs.component';
import {SearchComponent} from '../../../modules/search/search.component';
// module path. Created for avoid copy/paste
const BUILT_MODULE_PATH: string = '/built/application/partials/header/';
#Component({
selector: 'cgm_header',
templateUrl: `${BUILT_MODULE_PATH}header.component.html`,
directives: [BreadcrumbsComponent, SearchComponent],
styleUrls: [`..${BUILT_MODULE_PATH}header.component.css`],
})
export class HeaderComponent {
public title: string = 'Header';
// contains header data
public headerData: HeaderDataInterface = {
'searchPlaceholder': 'Search for Patient Name, MRN or MPID...',
'logOutLabel': 'Log out'
};
}
There is breadcrumb component
import {ROUTER_DIRECTIVES, Router} from 'angular2/router';
const builtModulePath: string = '/built/application/breadcrumbs/';
#Component({
selector: 'sgm_breadcrumbs',
templateUrl: `${builtModulePath}breadcrumbs.component.html`,
styleUrls: [`..${builtModulePath}breadcrumbs.component.css`],
directives: [ROUTER_DIRECTIVES]
})
export class BreadcrumbsComponent implements OnInit {
private staticData = {
'title': 'Breadcrumbs',
'homeName': 'Home',
'dashboardName': 'Dashboard'
}
constructor(private _router: Router, private _injector: Injector) { }
}
ngOnInit() {
this._router.subscribe((value) => {
let instructions = [];
//console.log(this._router);
this._router.recognize(value).then(instruction => {
this.handleRouterRecognize(instruction);
});
update
<script src="https://code.angularjs.org/2.0.0-beta.14/router.dev.js"></script>
is missing in index.html Plunker example
original
Try without templateUrl (use template instead). There were some related issues especially with async tests.
To set up tests use
// Somewhere in the test setup
import {setBaseTestProviders} from 'angular2/testing';
import {
TEST_BROWSER_PLATFORM_PROVIDERS,
TEST_BROWSER_APPLICATION_PROVIDERS
} from 'angular2/platform/testing/browser';
setBaseTestProviders(TEST_BROWSER_PLATFORM_PROVIDERS,
TEST_BROWSER_APPLICATION_PROVIDERS);
See also https://github.com/angular/angular/blob/master/CHANGELOG.md#200-beta2-2016-01-28