Test Assignments

In recent years I have applied to numerous development jobs driven by my will to develop my career and find better pay. It’s common nowadays for companies to give test assignments supposed to verify the candidate’s coding skills, as well as his/her ability to organize work. There is no test assignment I have failed to fulfil, but there are many times when I failed to explain it properly in a technical interview discussing my solution. I am a self-taught developer and have no formal technical education (excluding the high school where I specialized in microprocessors – a more hardware-oriented field of study). So, when the technical interviewer says “Nice solution, but can you describe the cyclomatic complexity of it?” I am done.

Honestly, I am aware of my skills, strengths and weaknesses. I haven’t gained experience with a lot of modern and trendy technologies that well-paying companies require. What kept me in the game for 15 years is mostly my ability to troubleshoot complex problems and provide simple solutions to them. Additionally, I have excellent communication skills, and I can explain complex technical issues to non-technical stakeholders in a way that is easy to understand. This has proven valuable in many situations, where I have been able to build strong relationships with clients and stakeholders and ensure that everyone is on the same page. That’s why my recent employers trust me to mentor and onboard others, not because of my top-notch up-to-date experience with all the fancy new technologies that popped up recently.

Anyway. This post is a short review of what I’ve done as coding challenges in recent years. I hope it’s a pretty comprehensive code base proving my ability to solve problems with code. Honestly, if I have to write yet another code assignment, I feel better working on something else and fuck development.

Continue reading

How to test for uniqueness of value in Yup.array?

Imagine you have a form with a dynamic amount of inputs – in my case, it is an array of objects holding “name” and “surname” properties and you need to validate that all objects in this array have unique name property.

Example schema:

const users = yup.array().of(yup.object().shape({
    name:  yup.string(),
    surname: yup.string(),
}))

How can you test for uniqueness? There is no built-in validator, but you can create a custom one easily extending Yup.test.  This validator allows you to add a test function to the validation chain. Tests are run after any object is cast. In order to allow asynchronous custom validations all (or no) tests are run asynchronously. A consequence of this is that test execution order cannot be guaranteed.

All tests must provide a name, an error message and a validation function that must return true when the current value is valid and false or a ValidationError otherwise. To make a test async return a promise that resolves true or false or a ValidationError.

For the message argument you can provide a string which will interpolate certain values if specified using the ${param} syntax. By default, all test messages are passed a path value which is valuable in nested schemas.

The test function is called with the current value.

const users = yup.array().of(yup.object().shape({
    name:  yup.string(),
    surname: yup.string(),
})).test(
    'unique',
        t('step2.validation_errors.duplicate').toString(),
        (value) => {
          if (!value) return true;

          const unique = value.filter((v: any, i: number, a: any) => a.findIndex((t: any) => (t.name === v.name && t.surname === v.surname)) === i);
          return unique.length === value.length;
    }
)

Because the uniqueness check is not related to a particular element of the users object but is a general validation constraint for the whole object, the error message will be populated as “errors.people” property of Formik. That’s why I am checking if the erros.users is a string – if it is a string, I should display a general error above all the user’s fields, but if it is an array of errors – it contains errors for a particular index of the users array.

{typeof errors.users === 'string' && <ErrorMessage
name="users"
component="div"
className="elementor-field-group mt-2 text-sm text-red-600 dark:text-red-500"
/>}

GSConnect doesn’t mount my phone on Manjaro Gnome, this is the solution

Hi there! I am using the Gnome shell extension GSConnect on Manjaro Gnome to share files from my phone to my laptop. There is an option called “Mount” that initially didn’t work on Manjaro but I found a solution and it now works like a charm!

All you need to do is to edit the file /etc/ssh/ssh_config

sudo vim /etc/ssh/ssh_config

and add to the end of the file the following:


Host 192.168.*.*
HostKeyAlgorithms +ssh-rsa

Install docker and docker-compose on Linux Mint 20.3

Issue the following commands in the terminal, one by one and you are ready to go! It’s simple as that 🙂

#docker setup
echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable" | sudo tee /etc/apt/sources.list.d/docker.list
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io pigz

#execution permission
sudo usermod -aG docker $USER

#docker compose
sudo curl -L "https://github.com/docker/compose/releases/download/2.2.3/docker-compose-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose</pre>

Fingerprint reader 0a5c:5843 Broadcom Corp. 58200 Ubuntu / Linux mint driver install

First, we need to checkout the following repo containing the driver:

git clone https://git.launchpad.net/~oem-solutions-engineers/libfprint-2-tod1-broadcom/+git/libfprint-2-tod1-broadcom/

Then go into the cloned folder and issue the following commands:

sudo sh install.sh
python3 debian/update-fw.py

You may need to restart the laptop in order the changes to be applied.

Finally, enable fingerprint login using the following command:

sudo pam-auth-update

Accessing Samba on Manjaro: failed to retrieve share list from server

A few days ago I got my shiny new StarBook Mk V and installed Manjaro on it for the very first time. I have no prior experience neither with Arch-based distros not rolling releases. Anyway, soon after I installed it I realized that I can’t access my homemade NAS server over Samba. I have a samba network at home with a mix of Linux (Linux Mint, Manjaro) and Windows 10 (don’t judge me) computers. Samba has always worked well to connect to each other. But now, when opening smb://192.168.1.6 in Gnome file manager I get this error: Failed to retrieve share list from server: Invalid argument

After quick duckling I found the solution: everything you need to do is to add these two lines in the global section of /etc/samba/smb.conf file on the server

client min protocol = CORE
server min protocol = CORE

and then restart it:

sudo service smbd restart

Voila!

P.S. The solution is based on the original post on the Manjaro forums here.

How to use bootstrap icons in React project

There are a few ways to go about it but I found this way to be the easiest and simple. First of all, download the package and add it to your dependencies.

npm i bootstrap-icons --save

Then add this line to your styles.css file at the top of your index.js file

import 'bootstrap-icons/font/bootstrap-icons.css';

Now, whenever you write an HTML with i tag with the bi code like below, you’ll see the icon appear!

<i class="bi bi-house"></i>

For example, go to https://icons.getbootstrap.com/icons/house/ we can see the code to the right that the code snippet is indeed “bi bi-house” for the house icon.

PHP Warning: PHP Startup: mcrypt: Unable to initialize module

If you have installed multiple PHP versions using PPA maintained by Ondrej Surý you may end up with the following error message:

PHP Warning: PHP Startup: mcrypt: Unable to initialize module
Module compiled with module API=20190902
PHP compiled with module API=20170718

This is caused by a misconfiguration: the php.ini file is pointing to the latest version of mcrypt instead of the one compiled for PHP 7.2. To fix that you have to correct the path to the extension. Open the file for editing:


sudo vi /etc/php/7.2/cli/conf.d/mcrypt.ini

and replace extension=/usr/lib/php/20190902/mcrypt.so with extension=/usr/lib/php/20170718/mcrypt.so. Do the same for /etc/php/7.2/fpm/conf.d/mcrypt.ini file.

If you have the module mcrypt.so listed in /etc/php/7.2/cli/php.ini or /etc/php/7.2/fpm/php.ini – delete it to avoid “PHP Warning: Module ‘mcrypt’ already loaded in Unknown on line 0” error

Install the latest versions of Vagrant and VirtualBox on Linux Mint 19.2

I use Linux Mint 19.2 as daily driver on my ThinkPad L480. This step by step tutorial will guide you through the process of getting the latest versions of VirtualBox and Vagrant instead of the outdated versions available in the official Ubuntu repositories.

VirtualBox and Vagrant receive updates on Linux much often than the repositories update. If you want to consistently get these updates when they become available, you’ll want to add VirtualBox and Vagrant repository to your system. This will allow you to get notified for new versions and update trough Linux Mint Update Manager and apt.

Continue reading

Mask email address for GDPR reasons with JavaScript

This is a simple JavaScript function that will mask your email address following this pattern:

  • If it’s not an email, the input string will be returned without modification.
  • If the first part of the email is shorter than 4 characters, the entire username will be masked (me@example.com => *@e*****e.com)
  • If the domain part of the email is shorter than 4 symbols, the entire domain will be masked
    (username@abc.com => u******e@***.com
  • The TLD part (.com/.net/.org and etc) is never masked
  • If the input string contains multiple emails (for example the whole log message from the server), all email addresses found in the string will be processed.
/**
 * Mask email address with asterisks to comply GDPR
 * john.doe@example.com => j******e@e****e.com
 * @param {string} emailAddress email address
 * @returns {string} masked email address
 */
function maskEmailAddress (emailAddress) {
	function mask(str) {
		var strLen = str.length;
		if (strLen > 4) {
			return str.substr(0, 1) + str.substr(1, strLen - 1).replace(/\w/g, '*') + str.substr(-1,1);
		} 
		return str.replace(/\w/g, '*');
	}
	return emailAddress.replace(/([\w.]+)@([\w.]+)(\.[\w.]+)/g, function (m, p1, p2, p3) {		
		return mask(p1) + '@' + mask(p2) + p3;
	});
	
	return emailAddress;
}

return maskEmailAddress('random string username@example.com test');