Pre-interview testing for a front-end software engineer position in 2018

Description: required skills were Vanilla JS, HTML5, CSS + some experience with good old jQuery library :) Basic knowledge of LESS, SASS, ECMAScript 6, Node.js, Gulp, Webpack, Underscore, JSDoc, VCS. And a strong desire to make UX better.

1. Replace a piece of text in an HTML fragment below using only Vanilla JavaScript. Leave <span> element untouched.

<div class="example">Two plus two <span>equals</span> - five</div>

Solution:

var elem = document.getElementsByClassName('example')[0]
elem.lastChild.nodeValue = ' - four'

2. Let's assume that you have such legacy code in your project. Simplify it as much as possible using jQuery

document.getElementById('x1')
            .getElementsByTagName('div')[4]
            .closest('#x1 > div').parentNode
            .childNodes[2].firstChild
            .querySelect('*[id="f"]')
            .textContent = 'Hello!';

Solution:

// * childNodes[2] and children(':eq(2)') will both work the same if there is no extra symbols between html tags 

$('#x1 > div').eq(4)
			  .parent('div#x1').children(':eq(2)')
			  .children(':first-child')
			  .find('#f').text('Hello!');

3. Using RegExp write a URL validation function. Valid URL-s shall meet the following criteria:


Valid example URL: https://c52.website.lh:8080

Solution:

function validate(url) {
	const r = /^(ftp|https?):\/\/((c[1-9][0-9]?|m|m-test)\.)?website\.[a-zA-Z\-]{2,64}(:8080)?$/;
	return r.test(url);
}

// test!

// good cases:
console.log('https://c52.website.lh:8080 ' + validate('https://c52.website.lh:8080'));
console.log('http://c52.website.lh:8080 ' + validate('http://c52.website.lh:8080'));
console.log('ftp://c52.website.lh:8080 ' + validate('ftp://c52.website.lh:8080'));
console.log('http://m.website.lh:8080 ' + validate('http://m.website.lh:8080'));
console.log('http://m-test.website.lh:8080 ' + validate('http://m-test.website.lh:8080'));
console.log('http://c82.website.lh:8080 ' + validate('http://c82.website.lh:8080'));
console.log('http://c82.website.lh:8080 ' + validate('http://c82.website.lh:8080'));
console.log('http://c82.website.lh ' + validate('http://c82.website.lh'));
console.log('http://c82.website.ua ' + validate('http://c82.website.ua'));
console.log('http://website.ua ' + validate('http://website.ua'));

// bad cases:
console.log('sftp://c52.website.lh:8080 ' + validate('sftp://c52.website.lh:8080'));
console.log('ftp://c52.website.lh:8081 ' + validate('ftp://c52.website.lh:8081'));
console.log('ftp://k.website.lh:8080 ' + validate('ftp://k.website.lh:8080'));
console.log('ftp://k-test.website.lh:8080 ' + validate('ftp://k-test.website.lh:8080'));
console.log('ftp://c102.website.lh:8080 ' + validate('ftp://c102.website.lh:8080'));
console.log('http://c10.vebsite.lh:8080 ' + validate('http://c10.vebsite.lh:8080'));
console.log('http://c10..org:8080 ' + validate('http://c10..org:8080'));
console.log('http://website.org:8080/page ' + validate('http://website.org:8080/page'));
console.log('http://website.org:8080?param=true ' + validate('http://website.org:8080?param=true'));
console.log('http://website.ua#section_one ' + validate('http://website.ua#section_one'));

4. Apply styles (LESS or SASS) to a list below to match it's view with expected result on a screenshot:

<div class="example">
    <ul>
        <li>Item 1</li>
        <li>Item 2
            <ul>
                <li data-value="1">sub-item</li>
                <li data-value="2">sub-item</li>
                <li data-value="3">sub-item</li>
            </ul>
        </li>
        <li>Item 3
            <ul>
                <li data-value="4">sub-item</li>
            </ul>
        </li>
    </ul>
</div>

Solution:

.example ul {
  list-style: disk;

  li:first-child {
    font-weight: bold;
  }

  li:only-child {
    font-weight: normal;
	}

  ul {
    list-style: none;
    margin-left: -0.8em;

    li {
      position:relative;
      padding-left: 0.7em;
      margin-bottom: 0.1em;

      &:before {
      content: '';
      height: .3em;
      width: .3em;
      background: #000;
      position: absolute;
      transform: rotate(45deg);
      top: .45em;
      left: .15em;
      }

      &:after {
      content: ', 'attr(data-value);
      }

    }

  }

}

5. Count how many characters which ASCII code is a multiple of 3 in a string str without using loops (for, while, do) and additional variables. Make your code as compact as possible.

Solution:

str.split('')
    .map(char => char.charCodeAt())
    .filter(charCode => charCode % 3 == 0)
    .length

6. Create a function that will transform an array of integers to match following conditions:

const input = [-2, 2, 4, 6, 8, 10, 3, 5, 7, 9, -1, -11];
func(input); // [ 10, 8, 6, 4, 2, -2, -11, -1, 3, 5, 7, 9 ]

Solution:

function func(arr) {
    const even = arr.filter(function(a) {
        if (a % 2 == 0) { return a; }
    });
    const odd = arr.filter(function(a) {
        if (a % 2 != 0) { return a; }
    });

    return even.sort(function(a, b) { return b - a; })
        .concat(odd.sort(function(a, b) { return a - b; }));
}

7. Define a BaseClass with which the expressions on the last two lines will become true

class BaseClass {
    // ... your code
}
class MyClass extends BaseClass {
    result(a, b) {
        this.a = a;
        this.b = b;
        return 100 - this.a + this.b;
    }
}
let m = new MyClass();
m.result(10, 20) === 90;
m.result(20, 10) === 110;

Solution:

set a(val) {
  this.a1 = -val;
}
set b(val) {
  this.b1 = -val;
}
get a() {
  return this.a1;
}
get b() {
  return this.b1;
}

8. Figure out the best CSS selector to paint text below in black color. Consider the rest of the CSS code that must stay below.

<section class="section" id="section">Green text</section>
// <-- Your selector

// ...

section.section {color: red}
.section {color: green}
section#section {color: yellow}
section#section.section {color: pink}
section.section {color: red}

Solution:

body section#section.section {color:black;}

9. Simplify following function as much as possible.

const f = (x) => {
	let data,
		x2 = new Number(`+${x}`),
		x3 = x / {toNumber() {return 5}};
	data = {
		isX: x3 === x3,
		d: Boolean(34),
		n: x === x2,
	};
	if (!!data.isX ? data.d : data.n) {
		return Math.ceil(x) >> x2;
	} else {
		return (Math.trunc(x) << 0) ** 0b10;
	}
};

Solution:

const f = (x) => {
	return (Math.trunc(x) << 0) ** 2;
};