Check out our Angular Book Series.

How do I set a Custom Header on an Angular HttpClientTestingModule Test?

In a few other posts I wrote about how to access custom headers in an Angular GET HTTP call and how to set custom headers in an Angular PUT or POST call.

But, how do I test those methods creating a custom header? It isn't hard.

Let's assume I'm trying to test code like this:


let mySavedCustomHeader;
makeServiceCall(): Observable<object | MyCustomClass> {
return this.http.get(`url`, { observe: 'response' })
map((response: HttpResponse<object>) =>
{
// save header
mySavedCustomHeader = response.headers.get('my-custom-header-name');

// other processing as needed
Object.assign(new MyCustomClass(), response.body)
return myCustomResponse;
})
}

There is a method, presumably on a service. It makes a service call to some service and passes in a configuration object that says "return the response. The result handler accesses the header object in order to get our custom header returned from the service. Then it does other processing. this should be relatively straight forward.

So, how do we test this?

First, set up your TestBed, be sure to load the HttpClientTestingModule:


let service, httpMock;

beforeEach(async(() =>
{
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule
],
providers: [
MyCustomService,
]
}).compileComponents()
.then (() => {
service = TestBed.get(MyCustomService
httpMock = TestBed.get(HttpTestingController);
});
}));

This code saves the service and httpMock values for later use in our test.

Start the test:


it('should call REST Endpoint with custom header', () =>
{
// all our other code will go here
});

First thing we want to do is make the service method. It returns an Observable so we'll subscribe to it and add some tests.


service.makeServiceCall().subscribe((value) =>
{
expect(service.mySavedCustomHeader).toBe('something');
});

Inside the service result handle we check for the custom header value on the service and make sure it was set. The assertions inside the result handler will run as the last piece of this method, even though the come first. Nothing has triggered the result handler yet.

How look for the mock HTTP call


const request = httpMock.expectOne('url');

I'll often run some assertions on the requestt


expect(request.method).toEqual('get');

Now create an HTTPHeader object:


const HttpHeader = {}
HttpHeader['my-custom-header-name'] = 'something';

And finally, flush the HTTP call:


req.flush(SomeCustomObjectWeDidNotCreateHere, {
headers: new HttpHraders(HttpHeader)
});

And that should be all you need to pass your custom header to the from your test into your service code.

How can I set headers in an Angular POST or PUT request?

In my previous article I spoke about accessing HTTP header values in an Angular GET request. Now, I'm going to show you how to set them as part of an HTTP PUT or POST request.

A simple update, might go something like this:


saveItem(item: ItemClas): Observable<Item> {
return this.http.put(`url`, item)
.pipe(
map(response =>
{
// process response
return response
})
);
}

We call a simple http.put() give it the URL and the item w are updating is the body. We process, and return the results. All good; this works great.

But, what happens when we want to send a custom header to the request? There is third parameter to a put() or post() call . It is a configuration object, and we can include our headers in there.

First, create the header:


const headerObject = {};
headerObject['my-header-name'] = my-header-value;

Then create the configuration object, with a headers property, that has the value of HttpHeaders object.


return this.http.put(`url`, item, {headers: new HttpHeaders(headerObject),})

That's all you need to properly add the header to the service call.

How do I get the versions of all installed Node Modules?

I've been working on an Angular project with my team, and we ran into a situation where tests were failing for a couple of team members, but working fine for everyone else. It was infuriating. We decided the issue must be with a version mismatch of some library, as opposed to the test itself.

Node libraries, by definition, have a lot of inner dependencies. How do we get a list of all the top level libraries installed on each user's respective machine? It's easy:


npm list -global -depth 0

The npm list command will give you the list. The `-global` flag will tell you to list all node packages installed globally.

The depth will give us the top level package, but none of the internal dependencies.

Run this and I get something like this:

I only have the Angular CLI installed globally.

To get a list of locally installed libraries, you can just drop out the global flag:


npm list -depth 0

If you want see the full list of dependencies, you can leave out the depth argument entirely.

Using this approach, we were able to determine the differences in installed base of the affected users vs the ones who could still run tests. It was a good first step in debugging the issue.

Lightsabers from Galaxy's Edge

I made some light sabers at Galaxy Edge in Disney World. Lots of fun:

How can I prevent an image from being dragged in my browser?

I've been doing some work on an Angular project with Dragula. I disabled our draggable div under certain conditions, but our users were still able to drag an image that lied within the Dragula div. Dragula prevented the drop, so our data was not put in a comprimising state, but it was confusing to our users that they could drag soemthing and not drop it.

Once I disabled Dragula on the div, the users were making use of default browser functionality. How can I prevent that?

There doesn't seem to be an easy cross browser way to do it, so I had to implement a few solutions.

First, for Chrome, I was able to use some CSS.


.no-drag{
-webkit-user-drag: none;
}

This web kit specific CSS extension prevents the item from being dragged.

Apply it to your imagE:


<img src="something" class="no-drag" />

But that did not solve the issue in Firefox. To do that I had to add the draggable attribute.


<img src="something" class="no-drag" draggable="false"/>

At this point it worked in both Firefox and Chrome and I stopped testing.

How do I use a compareWith Function with Angular Material?

In this screencast I talk about using a compareWith function with Angular Material.

Find the original vid on YouTube and check out the source on GitHub

Where is the SQL Server 2019 Configuration Manager?

The SQL Server configuration Manager is a tool used to configure the client. Primarily I use it to set up aliases, so 'DotComItDev' can point to my local dev server's IP Address on my local network. It is convenient not to have to remember the IP address every time I need to connect to the server.

I was setting up a new machine and installing the SQL Server Management Studio and could not find this tool. I know it used to be available from the start menu, but it no longer is.

At some point, it turned into an MMC Plugin that you could access / open using files on your computer. You can find info about that here. However, my client install of Management Studio 2019 did not include this file. I would have sworn it did when I installed SQL Server Management Studio 2017.

The solution to get this tool on my machine was to install the developer edition of SQL Server.

From there you can choose shared Features => Client Tools Connectivity. You do not actually need to install the server to get this. In most cases I do not need a server on the machine and am fine with just client tools on my dev machine.

See this screenshot:

Once I did that, I could access the plugin at C:\Windows\SysWOW64\SQLServerManager15.msc .

Launching this file would open the Configuration Manager:

You can configure this to your hearts content.

My Surface Laptop 3 is Losing Battery Life when Shut Down

I went on a recent vacation with my Surface Laptop 3 and was shocked to learn that the computer was losing battery life overnight after I had shut it down.

A Laptop that loses battery life while off is the least useful thing ever. I woke up having gone from 70% battery life to 0.

There is a bunch written about this on the Internet. My solution was to disable fast startup.

Bring up Windows Settings and select System,, and then power and sleep.

Select the "Additional Power Settings" link on the right side of the window.

Click "Choose what the power button does" from the left menu.

Then click the "Change Settings that are Currently Available" link.

Under shut down settings, be sure that Turn on Fast Startup (recommended) is unchecked.

Save your changes and you should be good to go.

I believe this fast startup is keeping the computer active in some manner which is depleting battery life.

I did a lot of reading before finding a solution that worked and didn't require me to go into the registry.

Hopefully this works for you too.

My Windows Software is too small on my High DPI Screen, how do I fix it?

How do I test nativeElement.focus in Angular?

In last week's post I wrote about setting focus on an element with Angular.

This week I wanted to write tests behind that code.

A Review

First, let's review what we want to test. We have a loop of inputs in the HTML Template and access them in the component class using the ViewChildren() metadata:


@ViewChildren('input') inputs: QueryList<ElementRef>;

Then we have an onClick() method which accepts an input and determines which element to set focus too:


onClick(index) {
this.inputs.toArray()[index].nativeElement.focus();
}

As a good developer, I of course, want to write tests against that onClick() method.

Write the Tests

If you're building off last week's project, you can open up the app.component.spec.ts file. You probably already have a beforeEach() which creates the basic application. Let's add a new describe block to the file:


describe('onClick()', () =>
{
});

Good start, let's add some variables:


let app;
const e1: ElementRef = new ElementRef({focus() {} } );
const e2: ElementRef = new ElementRef({focus() {} } );

I created one app variable to reference the component, and two ElementRef constants. When creating an ElementRef we pass in a nativeElement object. For the purposes of this test, I created a mock object with a focus() method. In production code I would have formalized a mock class to represent a nativeElement.

Now, let's add a beforeEach:


beforeEach(() =>
{
});
</code>

Nothing interesting here. Inside the beforeEach() let's get access to the app:

<code
const fixture = TestBed.createComponent(AppComponent);
app = fixture.debugElement.componentInstance;

This gets access to the fixture and saves the app for future use. Now detectChanges():


fixture.detectChanges();

This forces the component to render once, which will create all the viewChildren and populate the inputs variable.

Now, add spys for the focus method on our custom elementRef objects:


spyOn(e1.nativeElement, 'focus');
spyOn(e2.nativeElement, 'focus');

Our code will check on these spys to make sure the appropriate element was focused on based on our inputs in the onClick() method.

I want to do one more spy:


spyOn(app.inputs, 'toArray').and.returnValue([e1, e2]);

When our onClick() method tries to convert the inputs into an array, this gives us complete control over what the onClick() method is accessing. Even though the elements in the view are properly rendered, using this spy with controlled return values gives us granular control over the test.

Now let's write a test:


it('should call focus on element 0', () =>
{
app.onClick(0);
expect(e1.nativeElement.focus).toHaveBeenCalled();
expect(e2.nativeElement.focus).not.toHaveBeenCalled();
});

This call s the onClick() method with a 0 index. It verifies that focus was called on e1, but not on e2.

We can write a second test using a different index value:


it('should call focus on element 1', () =>
{
app.onClick(1);
expect(e1.nativeElement.focus).not.toHaveBeenCalled();
expect(e2.nativeElement.focus).toHaveBeenCalled();
});

This calls the same onClick() method, with a different index, and swaps the checks making sure that focus() was called on the e2 element and not the e1 element.

Run the code:

Success!

That is one way to test how to set focus on an element using Angular.

Play with the code here

More Entries

All Content Copyright 2005, 2006, 2007, 2008, 2009 Jeffry Houser. May not be reused without permission
BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002.