Full documentation

The purpose of this project is to offer a client-side code runner with built-in testing capabilities. Its primary objective is to assist educators in providing students with a convenient way to assess their skills and identify areas of improvement. By sharing a link containing both a base code and corresponding tests, students can effectively evaluate their understanding and identify errors. This process allows students to gain practical experience with unit tests without the need for specific development platforms or the installation of dependencies.

Our testing methodology draws inspiration from Jest's syntax, albeit with certain limitations. It is important to note that our implementation is not as extensive as Jest, which benefits from a vast community and operates within a NodeJS environment rather than a browser.

Writing tests

Our test framework is based on Jest syntax, which is this:

describe('test "someFunction"', () => { it('test cases when functions raises errors', () => { expect(() => someFunction(1, 2, 3)).toThrow("some error message"); expect(() => someFunction(false)).toThrow(); }); it('test if function works with an array of positive numbers', () => { expect(someFunction([1, 2, 3])).toBe(6); }); }); //other tests //describe(....);

When you write and run your tests, the code and tests are appended to the URL. This allows you to easily share the URL with others, enabling them to utilize your test cases and enhance their JavaScript skills.

Similarly, the process works the other way around as well! People can copy the URL and share it back with you, allowing you to assist them in understanding the type of error they are encountering with Coolfee.

Tip: you might wanna shorten the URL before sharing using some URL-shortening service like t.ly.

Matchers

By now, you may have noticed that we employ matchers to validate conditions related to JavaScript functions. This approach enables us to verify the expected returns and errors that our functions should or should not produce.

The syntax for the expect...to call is: expect(*someValue*).*someMatcher*(*anotherValue*);

Now you can lean how to use every kind of matcher our framework allows:

toBe (strictly-equal)

The toBe matcher allows you to check for strict-equality (===), but it also kindly supports objects and arrays by using JSON stringify on both sides. Of course, for objects and arrays it is not the best approach, because the JSON string might differ from the original variable in a way it will fail, but should not.

Sample code: describe('test "someFunction"', () => { it('test if function works with an array of positive numbers', () => { expect(someFunction([1, 2, 3])).toBe(6); }); });

toEqual (object or array comparison)

The toEqual matcher allows you to check for equality, but takes into consideration object/array comparison (deep-equality) and number to string comparison (parseFloat). At the end, if these types are not match, it tries a simple equality comparison (==).

Sample code: describe('test "someFunction"', () => { it('test if function works with a string', () => { expect(someFunction("Lucas")).toEqual({name: "Lucas", birthday: '1990-09-07'}); }); });

toBeCloseTo (floating-point comparison)

The toBeCloseTo matcher check for number proximity. The default precision is 2 (decimal places) but you can set some specific precision to work with.
What it does is check if the two values are close enough, because JavaScript can be tricky with floating-point precision.

Sample code: describe('test "sum"', () => { it('test if function can sum floating-point numbers', () => { expect(sum(0.1, 0.2)).toBeCloseTo(0.3, 3); }); });

toBeUndefined

Of course you may use the typeof constructor and the toBe matcher, but it just feel right to compare undefined values with a dedicated matcher, right?
It fails only if the value is not undefined.

Sample code: describe('test "someFunction"', () => { it('test if function exists', () => { expect(someFunction).not.toBeUndefined(); }); it('test if function is type function', () => { expect(typeof someFunction).toBe("function"); }); it('test if function returns undefined if a negative numbers is supplied', () => { expect(someFunction(-1)).toBeUndefined(); }); });

toThrow (an error)

This matcher checks if a function fails generally or specifically, with an optional error message supplied.
Notice: you need to wrap the function call in a function itself, otherwise the test will raise an error to the platform instead of catching it.

Sample code: describe('test "thatFunction"', () => { it('test if thatFunction fails when called with negative numbers', () => { expect(thatFunction(-1)).toThrow(); //generally expect(thatFunction(-1)).toThrow("Negative numbers are not allowed"); //specifically }); it('test if thatFunction DON'T fail when called with positive numbers', () => { expect(thatFunction(1)).not.toThrow(); }); });

not (prefix)

The expect method allows you to combine it with the not prefix.
This means you can negate matchers, by testing the opposite of what they meant to.

Sample code: describe('test "thatFunction"', () => { it('test if thatFunction is defined', () => { expect(thatFunction).not.toBeUndefined(); }); it('test if thatFunction DON'T fail when called with positive numbers', () => { expect(thatFunction(1)).not.toThrow(); }); it('test if thatFunction does not return 0 when called with positive numbers', () => { expect(thatFunction(2)).not.toBe(0); }); });