Skip to content

Commit

Permalink
Replace AVA with Vitest
Browse files Browse the repository at this point in the history
Update dependencies
  • Loading branch information
bokub committed Sep 12, 2024
1 parent 147e5fb commit fcc95b3
Show file tree
Hide file tree
Showing 17 changed files with 4,639 additions and 211 deletions.
5 changes: 1 addition & 4 deletions .github/workflows/run.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,14 @@ jobs:

- name: Install dependencies
run: yarn
- name: Run tests
run: yarn test
- name: Check code style
run: yarn check-prettier
- name: Create test report
- name: Run tests
run: yarn coverage

- name: Update code coverage
uses: codecov/codecov-action@v4
with:
files: ./coverage.lcov
token: ${{ secrets.CODECOV_TOKEN }}

- name: Publish on npm
Expand Down
7 changes: 1 addition & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,2 @@
node_modules
package-lock.json
yarn.lock
coverage.lcov
.nyc_output

.idea
coverage
5 changes: 1 addition & 4 deletions .husky/pre-commit
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx pretty-quick --staged
npx lint-staged --concurrent false
1,016 changes: 1,016 additions & 0 deletions .nyc_output/17aa108a-c15b-44aa-9279-8b22d12f0124.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions .nyc_output/5805ed10-0841-4472-9de5-8422987137bc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
1,016 changes: 1,016 additions & 0 deletions .nyc_output/6b702cb5-aa8b-4929-bdb0-ccd69b1223db.json

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions .nyc_output/processinfo/17aa108a-c15b-44aa-9279-8b22d12f0124.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"parent": "5805ed10-0841-4472-9de5-8422987137bc",
"pid": 200486,
"argv": ["/usr/local/bin/node", "/home/boris/work/self/rgb-light-card/node_modules/ava/lib/worker/subprocess.js"],
"execArgv": [],
"cwd": "/home/boris/work/self/rgb-light-card",
"time": 1726131306727,
"ppid": 200446,
"coverageFilename": "/home/boris/work/self/rgb-light-card/.nyc_output/17aa108a-c15b-44aa-9279-8b22d12f0124.json",
"externalId": "",
"uuid": "17aa108a-c15b-44aa-9279-8b22d12f0124",
"files": ["/home/boris/work/self/rgb-light-card/card.js"]
}
13 changes: 13 additions & 0 deletions .nyc_output/processinfo/5805ed10-0841-4472-9de5-8422987137bc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"parent": null,
"pid": 200446,
"argv": ["/usr/local/bin/node", "/home/boris/work/self/rgb-light-card/node_modules/.bin/ava"],
"execArgv": [],
"cwd": "/home/boris/work/self/rgb-light-card",
"time": 1726131305767,
"ppid": 200435,
"coverageFilename": "/home/boris/work/self/rgb-light-card/.nyc_output/5805ed10-0841-4472-9de5-8422987137bc.json",
"externalId": "",
"uuid": "5805ed10-0841-4472-9de5-8422987137bc",
"files": []
}
13 changes: 13 additions & 0 deletions .nyc_output/processinfo/6b702cb5-aa8b-4929-bdb0-ccd69b1223db.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"parent": "5805ed10-0841-4472-9de5-8422987137bc",
"pid": 200487,
"argv": ["/usr/local/bin/node", "/home/boris/work/self/rgb-light-card/node_modules/ava/lib/worker/subprocess.js"],
"execArgv": [],
"cwd": "/home/boris/work/self/rgb-light-card",
"time": 1726131306717,
"ppid": 200446,
"coverageFilename": "/home/boris/work/self/rgb-light-card/.nyc_output/6b702cb5-aa8b-4929-bdb0-ccd69b1223db.json",
"externalId": "",
"uuid": "6b702cb5-aa8b-4929-bdb0-ccd69b1223db",
"files": ["/home/boris/work/self/rgb-light-card/card.js"]
}
17 changes: 17 additions & 0 deletions .nyc_output/processinfo/index.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"processes": {
"17aa108a-c15b-44aa-9279-8b22d12f0124": { "parent": "5805ed10-0841-4472-9de5-8422987137bc", "children": [] },
"5805ed10-0841-4472-9de5-8422987137bc": {
"parent": null,
"children": ["17aa108a-c15b-44aa-9279-8b22d12f0124", "6b702cb5-aa8b-4929-bdb0-ccd69b1223db"]
},
"6b702cb5-aa8b-4929-bdb0-ccd69b1223db": { "parent": "5805ed10-0841-4472-9de5-8422987137bc", "children": [] }
},
"files": {
"/home/boris/work/self/rgb-light-card/card.js": [
"17aa108a-c15b-44aa-9279-8b22d12f0124",
"6b702cb5-aa8b-4929-bdb0-ccd69b1223db"
]
},
"externalIds": {}
}
22 changes: 9 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,19 @@
"ngrok": "ngrok http http://localhost:3000",
"prettier": "prettier --write --ignore-path .gitignore .",
"check-prettier": "prettier --check --ignore-path .gitignore . ",
"test": "nyc ava",
"coverage": "nyc report --reporter=text-lcov > coverage.lcov",
"prepare": "husky install"
"test": "vitest",
"coverage": "vitest run --coverage",
"prepare": "husky"
},
"devDependencies": {
"@bokub/prettier-config": "^1.1.0",
"ava": "^3.12.1",
"@vitest/coverage-v8": "^2.0.5",
"browser-env": "^3.3.0",
"codecov": "^3.6.5",
"husky": "^7.0.0",
"nyc": "^15.0.0",
"husky": "^9.1.6",
"lint-staged": "^15.2.10",
"prettier": "^2.2.1",
"pretty-quick": "^3.1.1",
"serve": "^14.2.3",
"vitest": "^2.0.5",
"yamljs": "^0.3.0"
},
"files": [
Expand All @@ -42,10 +41,7 @@
"main": "card.js",
"prettier": "@bokub/prettier-config",
"repository": "bokub/rgb-light-card",
"ava": {
"require": [
"./test/_setup.js",
"./card.js"
]
"lint-staged": {
"*": "prettier --write --ignore-unknown"
}
}
171 changes: 171 additions & 0 deletions test/card.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import { describe, test, expect } from 'vitest';
import '../card';
const version = require('../package.json').version;

describe('RGB Light Card', () => {
test('Library shows a badge with the right version', () => {
const searchStr = `%c RGB Light Card %c v${version} %c`;
expect(logged.find((e) => e.indexOf(searchStr) > -1)).toBeTruthy();
});

test('Card has CSS style', () => {
const card = new RGBLightCard();
const css = card.content.parentNode.querySelector('style').innerHTML;
expect(css.indexOf('.wrapper')).toBeGreaterThan(-1);
expect(css.indexOf('.color-circle')).toBeGreaterThan(-1);
});

test('Errors are raised if config is invalid', () => {
const card = new RGBLightCard();
expect(() => card.setConfig({})).toThrowError('You need to define an array of colors');
expect(() => card.setConfig({ colors: {} })).toThrowError('You need to define an array of colors');
expect(() => card.setConfig({ entity: 'vacuum.robot', colors: [] })).toThrowError(
"Entity 'vacuum.robot' must be a light"
);
expect(() => card.setConfig({ entity: 'light.example', colors: [{ type: 'automation' }] })).toThrowError(
"Invalid type 'automation' for colors[0]"
);
expect(() => card.setConfig({ colors: [{}] })).toThrowError('You need to define entity or colors[0].entity_id');
expect(() =>
card.setConfig({ entity: 'light.example', colors: [{ type: 'scene', entity_id: 'light.example' }] })
).toThrowError("Invalid type 'scene' for colors[0]");
expect(() => card.setConfig({ colors: [{ entity_id: 'group.example' }] })).toThrowError(
"colors[0].entity_id 'group.example' must be a valid light entity"
);
expect(() => card.setConfig({ colors: [{ type: 'call-service' }] })).toThrowError(
'You need to define colors[0].action'
);
expect(() => card.setConfig({ colors: [{ type: 'action' }] })).toThrowError(
'You need to define colors[0].action'
);
expect(() => card.setConfig({ colors: [{ type: 'call-service', service: 'shitty_service' }] })).toThrowError(
"colors[0].action 'shitty_service' must be a valid action"
);
expect(() => card.setConfig({ colors: [{ type: 'action', action: 'shitty_service' }] })).toThrowError(
"colors[0].action 'shitty_service' must be a valid action"
);
expect(() => card.setConfig({ entity: 'light.example', colors: [{ hs_color: [0, 0] }] })).not.toThrow();
});

test('Clicking the icons call the right function', () => {
const card = new RGBLightCard();

const clickOnCircle = (index) =>
card.content.parentNode.querySelector(`.color:nth-child(${index + 1}) .color-circle`).click();

let called = {};
card.hass = {
callService(domain, service, payload) {
called = JSON.parse(JSON.stringify({ domain, service, payload }));
},
};

let vibrations = 0;
window.dispatchEvent = (event) => {
if (event.type === 'haptic') vibrations++;
};

card.setConfig({
entity: 'light.example',
colors: [
{ hs_color: [180, 50], brightness: 200 },
{
type: 'call-service',
service: 'homeassistant.restart',
service_data: { force: true },
},
{
type: 'action',
action: 'hue.hue_activate_scene',
data: { group_name: 'kitchen', scene_name: 'kitchen_blue' },
},
],
});

clickOnCircle(1);
expect(vibrations).toBe(1);
expect(called).toEqual({
domain: 'light',
service: 'turn_on',
payload: { entity_id: 'light.example', hs_color: [180, 50], brightness: 200 },
});

clickOnCircle(2);
expect(vibrations).toBe(2);
expect(called).toEqual({ domain: 'homeassistant', service: 'restart', payload: { force: true } });

clickOnCircle(3);
expect(vibrations).toBe(3);
expect(called).toEqual({
domain: 'hue',
service: 'hue_activate_scene',
payload: { group_name: 'kitchen', scene_name: 'kitchen_blue' },
});
});

test("Setting HASS creates the card, but doesn't update it", () => {
const card = new RGBLightCard();
delete card.content;
expect(card.content).toBeFalsy();
card.setConfig({ entity: 'light.example', colors: [] });
expect(card.content).toBeFalsy();
card.hass = null;
expect(card.content).toBeTruthy();
const oldContent = card.content;
card.hass = null;
expect(oldContent).toBe(card.content);
});

test('hide_when_off option works', () => {
const card = new RGBLightCard();
card.setConfig({ entity: 'light.example', colors: [] });
card.hass = { states: { 'light.example': { state: 'off' } } };
expect(card.content.classList.contains('hidden')).toBeFalsy(); // Not hidden

card.setConfig({ entity: 'light.example', colors: [], hide_when_off: true });
card.hass = { states: { 'light.example': { state: 'off' } } };
expect(card.content.classList.contains('hidden')).toBeTruthy(); // Hidden

card.hass = { states: { 'light.example': { state: 'unavailable' } } };
expect(card.content.classList.contains('hidden')).toBeTruthy(); // Hidden

card.hass = { states: { 'light.example': { state: 'on' } } };
expect(card.content.classList.contains('hidden')).toBeFalsy(); // Not hidden

card.setConfig({ colors: [], hide_when_off: true });
card.hass = { states: { 'light.example': { state: 'off' } } };
expect(card.content.classList.contains('hidden')).toBeFalsy(); // Not hidden
});

test('Card is added to window.customCards', () => {
new RGBLightCard();
expect(window.customCards.length).toBe(1);
expect(window.customCards[0]).toEqual({
type: 'rgb-light-card',
name: 'RGB Light Card',
description: 'A custom card for RGB lights',
preview: true,
});
});

test('Card has a stub config', () => {
let conf = RGBLightCard.getStubConfig({ states: {} });
expect(conf.entities[1].entity).toBe('light.example_light');

conf = RGBLightCard.getStubConfig({
states: {
'plop.light_1': { attributes: { supported_color_modes: ['hs'] }, entity_id: 'plop.light_1' },
'light.light_2': { attributes: { supported_color_modes: ['onoff'] }, entity_id: 'light.light_2' },
'light.light_3': {
attributes: { supported_color_modes: ['onoff', 'rgb'] },
entity_id: 'light.light_3',
},
},
});
expect(conf.entities.length).toBe(2);
expect(conf.entities[0].entity).toBe('light.light_3');
expect(conf.entities[1].entity).toBe('light.light_3');
expect(conf.entities[1].type).toBe('custom:rgb-light-card');
expect(conf.entities[1].colors.length).toBe(4);
});
});
36 changes: 20 additions & 16 deletions test/render-tests.js → test/render.test.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
const test = require('ava');
const YAML = require('yamljs');
import { describe, test, expect } from 'vitest';
import '../card';
import YAML from 'yamljs';

const circleMarkup = (background, innerText) =>
`<div class="color"><div class="color-circle" style="background: ${background};"></div><div class="color-label">${
innerText || ''
}</div></div>`;

const styleMarkup = (str) => `<style>${str.replace(/\s\s+/g, ' ')}</style>`;

const testCases = [
{
name: 'Test icon colors',
Expand Down Expand Up @@ -80,23 +82,25 @@ label_size: 10
`,
result:
styleMarkup(`
.wrapper { justify-content: space-around; margin-bottom: -3.5px; }
.wrapper.hidden { display: none; }
.color-circle { width: 28px; height: 28px; margin: 3.5px 7px 7px; }
.color-label { font-size: 10px; margin-bottom: 3.5px; }
`) +
.wrapper { justify-content: space-around; margin-bottom: -3.5px; }
.wrapper.hidden { display: none; }
.color-circle { width: 28px; height: 28px; margin: 3.5px 7px 7px; }
.color-label { font-size: 10px; margin-bottom: 3.5px; }
`) +
circleMarkup('rgb(234, 136, 140)') +
circleMarkup('rgb(251, 180, 140)') +
circleMarkup('rgb(135, 198, 237)', 'Blue'),
},
];

for (const testCase of testCases) {
test(testCase.name || 'Unnamed test', (t) => {
const card = new RGBLightCard();
if (testCase.config) {
card.setConfig(YAML.parse(testCase.config));
}
t.is(card.content.innerHTML, testCase.result);
});
}
describe('RGB Light Card renderings', () => {
for (const testCase of testCases) {
test(testCase.name || 'Unnamed test', () => {
const card = new RGBLightCard();
if (testCase.config) {
card.setConfig(YAML.parse(testCase.config));
}
expect(card.content.innerHTML).toBe(testCase.result);
});
}
});
File renamed without changes.
Loading

0 comments on commit fcc95b3

Please sign in to comment.