Skip to content
tinytip

Latest tips / 7

Use npm ci for a clean installation of your dependencies

March 2, 2022
#npm

You already now the npm install command, right? It installs your dependencies defined in your package.json and package-lock.json. It will reuse existing packages in your node_modules folder and may update the package-lock.json file to match the actual installed versions. This is fine for development, but it is not what you want on your build or testing server.

The npm ci command does a clean install of your dependencies. It removes the node_modules folder and re-installs the dependencies. It will make sure that the package-lock.json is up to date and will exit with an error if it is not. And will never update the package.json or package-lock.json.

# On your machine
npm install

# On your build or testing server
npm ci

See the npm documentation for more information.

Create clearer tests by nesting describe()

March 1, 2022
#testing #jest #jasmine

Testing Frameworks like Vitest, Jest and Jasmine provide a describe() function. It is useful to group your tests into logical groups. The function can be nested to create a hierarchy of tests and make the tests more readable.

In Angular for example, you will have the following spec file when creating a new component:

describe("AccordionComponent", () => {
it("should create", () => {
// ...
});
});

Instead of adding a lot of it() calls with long descriptions you can create multiple describe() blocks.

describe("AccordionComponent", () => {
describe("initial state is expanded", () => {
// Mock data, test utils, etc. for this describe() block
const initiallyExpanded = true;

it("should render the accordion title", () => {
// ...
});

it("should render the accordion content", () => {
// ...
});

it("should mark the accordion as expanded", () => {
// ...
});

it("should collapse the accordion when clicking on the title", () => {
// ...
});
});

describe("initial state is collapsed", () => {
it("should render the accordion title", () => {
// ...
});

it("should not render the accordion content", () => {
// ...
});

it("should mark the accordion as collapsed", () => {
// ...
});

it("should expand the accordion when clicking on the title", () => {
// ...
});
});
});

Jasmine shows all describe() blocks in the output and nests them in a tree structure.

Jasmine shows all nested describe blocks

CSS content-visibility hides the content of an element

February 28, 2022
#css

There are several ways to hide an element in CSS. display: none completely hides the element from view. visibility: hidden hides the element from view, but the element still occupies space in the layout.

The content-visibility property allows you to hide the content of an element, but not the element itself. Some styling like background and border will still be visible.

.element {
content-visibility: hidden;
}

See MDN Web Docs for more information and Browser support.

Angular Outputs can be RxJS Observables

February 27, 2022
#angular #rxjs

Angular uses the @Output decorator and the EventEmitter class to emit events to the parent component. But you can use RxJS streams instead.

The EventEmitter class is actually a wrapper around the RxJs Subject class. If you have an existing Subject or Observable that you want to use as an output, you can directly use it with the @Output decorator.

export class SearchComponent {
// With Angular EventEmitter
@Output()
search = new EventEmitter<string>();

// With RxJs Subject / Observable
@Output()
search = this.form.valueChanges.pipe(
debounceTime(500),
map((value) => value.term),
distinctUntilChanged()
);
}

CSS calc() requires unit

February 26, 2022
#css

Most CSS properties require a unit, for example padding: 10px. If you use 0 you can omit the unit, like padding: 0.

An exception is the calc() function, which always requires a unit, even for 0.

.example-class {
padding: 0; /* works */

height: calc(100vh - 0); /* does NOT work */
height: calc(100vh - 0px); /* works */
}

That is mainly important if you use CSS custom properties (aka variables) with a default value of 0 inside calc():

.example-class {
height: calc(100vh - var(--header-height, 0)); /* does NOT work */
height: calc(100vh - var(--header-height, 0px)); /* works */
}