å ç¢ã§ä¿¡é Œæ§ã®é«ãWebã¢ããªã±ãŒã·ã§ã³ã®ããã®Webã³ã³ããŒãã³ããã¹ãæŠç¥ã®å æ¬çã¬ã€ãããŠããããã¹ããšã³ã³ããŒãã³ãå颿è¡ã«çŠç¹ãåœãŠãŸãã
Webã³ã³ããŒãã³ãã®ãã¹ãïŒãŠããããã¹ã vs ã³ã³ããŒãã³ãåé¢
Webã³ã³ããŒãã³ãã¯ãåå©çšå¯èœã§ã«ãã»ã«åãããUIèŠçŽ ãäœæããããã®æšæºåãããæ¹æ³ãæäŸããããšã§ãããã³ããšã³ãéçºã«é©åœããããããŸãããçŸä»£ã®Webã¢ããªã±ãŒã·ã§ã³ã§Webã³ã³ããŒãã³ãããŸããŸãæ®åããã«ã€ããŠã峿 Œãªãã¹ããéããŠãã®å質ã確ä¿ããããšãæãéèŠã«ãªããŸãããã®èšäºã§ã¯ãWebã³ã³ããŒãã³ãã®2ã€ã®äž»èŠãªãã¹ãæŠç¥ã§ãããŠããããã¹ããšã³ã³ããŒãã³ãåé¢ãæ¢ããããããã®é·æãçæããããŠéçºã¯ãŒã¯ãããŒã«å¹æçã«çµ±åããæ¹æ³ãæ€èšŒããŸãã
ãªãWebã³ã³ããŒãã³ãããã¹ãããã®ãïŒ
ç¹å®ã®ãã¹ãæè¡ã«é£ã³èŸŒãåã«ãWebã³ã³ããŒãã³ãã®ãã¹ãããªãäžå¯æ¬ ãªã®ããçè§£ããããšãéèŠã§ãïŒ
- ä¿¡é Œæ§ïŒ ãã¹ãã«ãããWebã³ã³ããŒãã³ããç°ãªããã©ãŠã¶ãç°å¢ã§æåŸ éãã«æ©èœããããšãä¿èšŒãããäºæãã¬åäœããã°ãæå°éã«æããããŸãã
- ä¿å®æ§ïŒ ååã«ãã¹ããããã³ã³ããŒãã³ãã¯ãä¿å®ããªãã¡ã¯ã¿ãªã³ã°ã容æã«ãªãã倿޿ã«ãªã°ã¬ãã·ã§ã³ãå°å ¥ãããªã¹ã¯ãäœæžããŸãã
- åå©çšæ§ïŒ 培åºçãªãã¹ãã«ãããã³ã³ããŒãã³ããçã«åå©çšå¯èœã§ãããã¢ããªã±ãŒã·ã§ã³ã®ç°ãªãéšåãè€æ°ã®ãããžã§ã¯ãéã§èªä¿¡ãæã£ãŠçµ±åã§ããããšãæ€èšŒãããŸãã
- éçºã³ã¹ãã®åæžïŒ ãã¹ããéããŠéçºããã»ã¹ã®æ©ã段éã§ãã°ãçºèŠããããšã¯ãåŸã§æ¬çªç°å¢ã§ä¿®æ£ãããããå€§å¹ ã«ã³ã¹ããå®ããªããŸãã
- ãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã®åäžïŒ Webã³ã³ããŒãã³ãã®å®å®æ§ãšæ©èœæ§ã確ä¿ããããšã§ãããã¹ã ãŒãºã§æ¥œãããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã«è²¢ç®ããŸãã
Webã³ã³ããŒãã³ãã®ãŠããããã¹ã
ãŠããããã¹ãã¯ãåã ã®ã³ãŒãåäœãåé¢ããŠãã¹ãããããšã«çŠç¹ãåœãŠãŸããWebã³ã³ããŒãã³ãã®æèã§ã¯ããåäœããšã¯éåžžãã³ã³ããŒãã³ãã®ã¯ã©ã¹å ã®ç¹å®ã®ã¡ãœããã颿°ãæããŸãããŠããããã¹ãã®ç®æšã¯ãååäœãã³ã³ããŒãã³ããã¢ããªã±ãŒã·ã§ã³ã®ä»ã®éšåããç¬ç«ããŠãæå³ããã¿ã¹ã¯ãæ£ããå®è¡ããããšã確èªããããšã§ãã
Webã³ã³ããŒãã³ãã®ãŠããããã¹ãã®å©ç¹
- ãã现ãããã¹ãïŒ ãŠããããã¹ãã¯ãã¹ãããã»ã¹ã现ããå¶åŸ¡ã§ãããããã³ã³ããŒãã³ãã®æ©èœã®ç¹å®ã®åŽé¢ãåé¢ããŠãã¹ãããããšãã§ããŸãã
- é«éãªå®è¡ïŒ ãŠããããã¹ãã¯éåžžãéåžžã«é«éã«å®è¡ããããããéçºäžã«è¿ éãªãã£ãŒãããã¯ãåŸãããšãã§ããŸãã
- ãããã°ã®å®¹æãïŒ ãŠããããã¹ãã倱æããå Žåãå°ããåé¢ãããã³ãŒãçã®ã¿ããã¹ãããŠãããããåé¡ã®åå ãç¹å®ããã®ãéåžžã¯ç°¡åã§ãã
- ã³ãŒãã«ãã¬ããžïŒ ãŠããããã¹ãã¯é«ãã³ãŒãã«ãã¬ããžãéæããã®ã«åœ¹ç«ã¡ãã³ã³ããŒãã³ãã®ã³ãŒãã®å€§éšåããã¹ããããããšãä¿èšŒããŸãã
Webã³ã³ããŒãã³ãã®ãŠããããã¹ãã®èª²é¡
- Shadow DOMã®è€éãïŒ Shadow DOMã¯ã³ã³ããŒãã³ãã®å éšæ§é ãšã¹ã¿ã€ãªã³ã°ãã«ãã»ã«åããããããŠããããã¹ãã§Shadow DOMãæäœããã®ã¯å°é£ãªå ŽåããããŸãã
- äŸåé¢ä¿ã®ã¢ãã¯åïŒ ãã¹ã察象ã®åäœãåé¢ããããã«äŸåé¢ä¿ãã¢ãã¯åããå¿ èŠãããå Žåããããããã«ãããã¹ããè€éã«ãªãå¯èœæ§ããããŸãã
- å®è£ 詳现ãžã®çŠç¹ïŒ é床ã«å ·äœçãªãŠããããã¹ãã¯ãã³ã³ããŒãã³ãã®å éšå®è£ ããªãã¡ã¯ã¿ãªã³ã°ãããšå£ãããããè匱ã«ãªãå¯èœæ§ããããŸãã
Webã³ã³ããŒãã³ãã®ãŠããããã¹ãçšããŒã«ãšãã¬ãŒã ã¯ãŒã¯
Webã³ã³ããŒãã³ãã®ãŠããããã¹ãã«ã¯ãããã€ãã®äººæ°ã®ããJavaScriptãã¹ããã¬ãŒã ã¯ãŒã¯ã䜿çšã§ããŸãïŒ
- JestïŒ Facebookã«ãã£ãŠéçºãããåºã䜿çšãããŠãããã¹ããã¬ãŒã ã¯ãŒã¯ã§ããã®ã·ã³ãã«ããé床ãçµã¿èŸŒã¿ã®ã¢ãã¯æ©èœã§ç¥ãããŠããŸãã
- MochaïŒ ã¢ãµãŒã·ã§ã³ã©ã€ãã©ãªïŒäŸïŒChaiãAssertïŒãã¢ãã¯ã©ã€ãã©ãªïŒäŸïŒSinonïŒãèªç±ã«éžæã§ããæè»ãªãã¹ããã¬ãŒã ã¯ãŒã¯ã§ãã
- JasmineïŒ ã¯ãªãŒã³ã§åŠã³ãããæ§æãæã€ãããäžã€ã®äººæ°ã®ãããã¹ããã¬ãŒã ã¯ãŒã¯ã§ãã
Jestã䜿çšããWebã³ã³ããŒãã³ãã®ãŠããããã¹ãã®äŸ
ã«ãŠã³ã¿ãŒã衚瀺ãããŠãŒã¶ãŒããããã€ã³ã¯ãªã¡ã³ãã§ãã<my-counter>
ãšããååã®ã·ã³ãã«ãªWebã³ã³ããŒãã³ããèããŠã¿ãŸãããã
my-counter.js
class MyCounter extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: 'open' });
this._count = 0;
this.render();
}
increment() {
this._count++;
this.render();
}
render() {
this.shadow.innerHTML = `
<p>Count: ${this._count}</p>
<button id="incrementBtn">Increment</button>
`;
this.shadow.getElementById('incrementBtn').addEventListener('click', () => this.increment());
}
}
customElements.define('my-counter', MyCounter);
my-counter.test.js (Jest)
import './my-counter.js';
describe('MyCounter', () => {
let element;
beforeEach(() => {
element = document.createElement('my-counter');
document.body.appendChild(element);
});
afterEach(() => {
document.body.removeChild(element);
});
it('should increment the count when the button is clicked', () => {
const incrementBtn = element.shadowRoot.getElementById('incrementBtn');
incrementBtn.click();
expect(element.shadowRoot.querySelector('p').textContent).toBe('Count: 1');
});
it('should initialize the count to 0', () => {
expect(element.shadowRoot.querySelector('p').textContent).toBe('Count: 0');
});
});
ãã®äŸã¯ãJestã䜿çšããŠ<my-counter>
ã³ã³ããŒãã³ãã®increment
ã¡ãœãããšåæã«ãŠã³ãå€ããã¹ãããæ¹æ³ã瀺ããŠããŸãã`shadowRoot`ã䜿çšããŠShadow DOMå
ã®èŠçŽ ã«ã¢ã¯ã»ã¹ããããšã匷調ããŠããŸãã
ã³ã³ããŒãã³ãåé¢ãã¹ã
ã³ã³ããŒãã³ãåé¢ãã¹ãã¯ãã³ã³ããŒãã³ããã¹ããŸãã¯ããžã¥ã¢ã«ãã¹ããšããŠãç¥ãããéåžžã¯ã¢ããªã±ãŒã·ã§ã³ã®ä»ã®éšåããåé¢ããããããçŸå®çãªç°å¢ã§Webã³ã³ããŒãã³ãããã¹ãããããšã«çŠç¹ãåœãŠãŸãããã®ã¢ãããŒãã«ãããåšå²ã®ã¢ããªã±ãŒã·ã§ã³ã®è€éãã«åœ±é¿ãããããšãªããã³ã³ããŒãã³ãã®åäœãå€èгãããã³ãŠãŒã¶ãŒãšã®ã€ã³ã¿ã©ã¯ã·ã§ã³ãæ€èšŒã§ããŸãã
ã³ã³ããŒãã³ãåé¢ãã¹ãã®å©ç¹
- çŸå®çãªãã¹ãç°å¢ïŒ ã³ã³ããŒãã³ãåé¢ãã¹ãã¯ããŠããããã¹ããšæ¯èŒããŠããçŸå®çãªãã¹ãç°å¢ãæäŸããã³ã³ããŒãã³ããã¢ããªã±ãŒã·ã§ã³ã§å®éã«äœ¿çšãããç¶æ³ã«è¿ãæèã§ãã®åäœããã¹ãã§ããŸãã
- ããžã¥ã¢ã«ãªã°ã¬ãã·ã§ã³ãã¹ãïŒ ã³ã³ããŒãã³ãåé¢ãã¹ãã¯ãç°ãªããã«ãéã§ã³ã³ããŒãã³ãã®ã¹ã¯ãªãŒã³ã·ã§ãããæ¯èŒããŠãæå³ããªãèŠèŠçãªå€æŽãæ€åºããããžã¥ã¢ã«ãªã°ã¬ãã·ã§ã³ãã¹ããå¯èœã«ããŸãã
- ã³ã©ãã¬ãŒã·ã§ã³ã®åäžïŒ ã³ã³ããŒãã³ãåé¢ããŒã«ã¯ãéçºè ããã¶ã€ããŒãã¹ããŒã¯ãã«ããŒãã³ã³ããŒãã³ããç°¡åã«ã¬ãã¥ãŒãããã£ãŒãããã¯ãæäŸã§ããèŠèŠçãªã€ã³ã¿ãŒãã§ãŒã¹ãæäŸããããšããããããŸãã
- ã¢ã¯ã»ã·ããªãã£ãã¹ãïŒ åé¢ãããã³ã³ããŒãã³ãã§ã¢ã¯ã»ã·ããªãã£ãã¹ãã宿œããæ¹ãç°¡åã§ãã¢ã¯ã»ã·ããªãã£åºæºãæºãããŠããããšã確èªã§ããŸãã
ã³ã³ããŒãã³ãåé¢ãã¹ãã®èª²é¡
- å®è¡é床ã®äœäžïŒ ã³ã³ããŒãã³ãåé¢ãã¹ãã¯ããã©ãŠã¶ç°å¢ã§ã³ã³ããŒãã³ããã¬ã³ããªã³ã°ããå¿ èŠãããããããŠããããã¹ããããå®è¡ãé ããªãå¯èœæ§ããããŸãã
- ã»ããã¢ããã®è€éåïŒ ã³ã³ããŒãã³ãåé¢ãã¹ãç°å¢ã®ã»ããã¢ããã¯ããŠããããã¹ãç°å¢ã®ã»ããã¢ãããããè€éã«ãªãå¯èœæ§ããããŸãã
- äžå®å®æ§ã®å¯èœæ§ïŒ ã³ã³ããŒãã³ãåé¢ãã¹ãã¯ããããã¯ãŒã¯é å»¶ããã©ãŠã¶ã®äžäžèŽãªã©ã®èŠå ã«ãããäžå®å®ïŒflakyïŒã«ãªããããåŸåããããŸãã
ã³ã³ããŒãã³ãåé¢ãã¹ãçšããŒã«ãšãã¬ãŒã ã¯ãŒã¯
ã³ã³ããŒãã³ãåé¢ãã¹ãã«ã¯ãããã€ãã®ããŒã«ãšãã¬ãŒã ã¯ãŒã¯ãå©çšå¯èœã§ãïŒ
- StorybookïŒ UIã³ã³ããŒãã³ããåé¢ããŠéçºããã³ãã¹ãããããã®äººæ°ã®ãããªãŒãã³ãœãŒã¹ããŒã«ã§ããStorybookã¯ãã³ã³ããŒãã³ããé²èЧããæäœããããã¥ã¡ã³ãã衚瀺ã§ããèŠèŠçãªç°å¢ãæäŸããŸãã
- CypressïŒ ã³ã³ããŒãã³ããã¹ãã«ã䜿çšã§ãããšã³ãããŒãšã³ããã¹ããã¬ãŒã ã¯ãŒã¯ã§ããCypressã¯ãã³ã³ããŒãã³ããšå¯Ÿè©±ãããã®åäœãã¢ãµãŒãããããã®åŒ·åãªAPIãæäŸããŸãã
- ChromaticïŒ Storybookãšçµ±åããŠããžã¥ã¢ã«ãªã°ã¬ãã·ã§ã³ãã¹ããšã³ã©ãã¬ãŒã·ã§ã³æ©èœãæäŸããããžã¥ã¢ã«ãã¹ããã©ãããã©ãŒã ã§ãã
- BitïŒ åå©çšå¯èœãªã³ã³ããŒãã³ããæ§ç¯ãææžåãæŽçããããã®ã³ã³ããŒãã³ããã©ãããã©ãŒã ã§ãã
Storybookã䜿çšããã³ã³ããŒãã³ãåé¢ãã¹ãã®äŸ
ãŠããããã¹ãã®äŸãšåã<my-counter>
ã³ã³ããŒãã³ãã䜿çšããŠãStorybookã§ããããã¹ãããæ¹æ³ãèŠãŠã¿ãŸãããã
.storybook/main.js
module.exports = {
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-interactions'
],
framework: '@storybook/web-components',
core: {
builder: '@storybook/builder-webpack5'
},
};
src/my-counter.stories.js
import './my-counter.js';
export default {
title: 'MyCounter',
component: 'my-counter',
};
const Template = () => '<my-counter></my-counter>';
export const Default = Template.bind({});
ãã®äŸã¯ã<my-counter>
ã³ã³ããŒãã³ãã®Storybookã¹ããŒãªãŒãäœæããæ¹æ³ã瀺ããŠããŸãããã®åŸãStorybookã®ã€ã³ã¿ã©ã¯ãã£ããªã€ã³ã¿ãŒãã§ãŒã¹ã䜿çšããŠã³ã³ããŒãã³ããæåã§ãã¹ãããããChromaticã®ãããªããžã¥ã¢ã«ãã¹ãããŒã«ãšçµ±åãããã§ããŸãã
é©åãªãã¹ãæŠç¥ã®éžæ
ãŠããããã¹ããšã³ã³ããŒãã³ãåé¢ãã¹ãã¯çžäºã«æä»çãªãã®ã§ã¯ãªãããããäºãã«è£å®ãåããWebã³ã³ããŒãã³ãã®å æ¬çãªãã¹ãã«ãã¬ããžãæäŸããããã«äœµçšãããã¹ãã§ãã
ãŠããããã¹ãã䜿çšããå ŽåïŒ
- ã³ã³ããŒãã³ãã®ã¯ã©ã¹å ã®åã ã®ã¡ãœããã颿°ããã¹ãããããã
- ã³ã³ããŒãã³ãã®å éšããžãã¯ãèšç®ãæ€èšŒããããã
- éçºäžã«è¿ éãªãã£ãŒãããã¯ãå¿ èŠãªå Žåã
- é«ãã³ãŒãã«ãã¬ããžãéæãããå Žåã
ã³ã³ããŒãã³ãåé¢ãã¹ãã䜿çšããå ŽåïŒ
- çŸå®çãªç°å¢ã§ã³ã³ããŒãã³ãã®åäœãšå€èгããã¹ãããããã
- ããžã¥ã¢ã«ãªã°ã¬ãã·ã§ã³ãã¹ããå®è¡ããããã
- éçºè ããã¶ã€ããŒãã¹ããŒã¯ãã«ããŒéã®ã³ã©ãã¬ãŒã·ã§ã³ãæ¹åããããã
- ã¢ã¯ã»ã·ããªãã£ãã¹ããå®è¡ããããã
Webã³ã³ããŒãã³ãã®ãã¹ãã«ããããã¹ããã©ã¯ãã£ã¹
Webã³ã³ããŒãã³ãããã¹ãããéã«åŸãã¹ããã¹ããã©ã¯ãã£ã¹ãããã€ã玹ä»ããŸãïŒ
- æ©æãã€é »ç¹ã«ãã¹ããæžãïŒ ãããžã§ã¯ãã®æåããéçºã¯ãŒã¯ãããŒã«ãã¹ããçµ±åããŸãããã¹ãé§åéçºïŒTDDïŒãããã€ãã¢é§åéçºïŒBDDïŒã®ã¢ãããŒããæ€èšããŠãã ããã
- ã³ã³ããŒãã³ãã®ãã¹ãŠã®åŽé¢ããã¹ãããïŒ ã³ã³ããŒãã³ãã®æ©èœãå€èгãã¢ã¯ã»ã·ããªãã£ãããã³ãŠãŒã¶ãŒãšã®ã€ã³ã¿ã©ã¯ã·ã§ã³ããã¹ãããŸãã
- æç¢ºã§ç°¡æœãªãã¹ãåã䜿çšããïŒ åãã¹ããäœãæ€èšŒããŠããããæç¢ºã«ç€ºãã説æçãªãã¹ãåã䜿çšããŸãã
- ãã¹ããåé¢ããïŒ åãã¹ããä»ã®ãã¹ãããç¬ç«ããŠãããå€éšã®ç¶æ ã«äŸåããªãããã«ããŸãã
- ã¢ãã¯ãè³¢ã䜿çšããïŒ ãã¹ã察象ã®åäœãåé¢ããããã«å¿ èŠãªå Žåã«ã®ã¿ãäŸåé¢ä¿ãã¢ãã¯åããŸãã
- ãã¹ããèªååããïŒ ãã¹ããç¶ç¶çã€ã³ãã°ã¬ãŒã·ã§ã³ïŒCIïŒãã€ãã©ã€ã³ã«çµ±åãããã¹ãŠã®ã³ãããã§èªåçã«å®è¡ãããããã«ããŸãã
- ãã¹ãçµæã宿çã«ã¬ãã¥ãŒããïŒ ãã¹ãçµæã宿çã«ã¬ãã¥ãŒããŠã倱æãããã¹ããç¹å®ãä¿®æ£ããŸãã
- ãã¹ããææžåããïŒ ãã¹ãã®ç®çãšåäœã説æããããã«ããã¹ããææžåããŸãã
- ã¯ãã¹ãã©ãŠã¶ãã¹ããæ€èšããïŒ äºææ§ã確ä¿ããããã«ãã³ã³ããŒãã³ããç°ãªããã©ãŠã¶ïŒChromeãFirefoxãSafariãEdgeïŒã§ãã¹ãããŸããBrowserStackãSauce Labsãªã©ã®ãµãŒãã¹ããããæ¯æŽããŸãã
- ã¢ã¯ã»ã·ããªãã£ãã¹ãïŒ axe-coreãªã©ã®ããŒã«ã䜿çšããŠãã³ã³ããŒãã³ããã¹ãæŠç¥ã®äžéšãšããŠèªåã¢ã¯ã»ã·ããªãã£ãã¹ããå®è£ ããŸãã
äŸïŒåœéåïŒi18nïŒWebã³ã³ããŒãã³ãã®å®è£ ãšãã¹ã
åœéåãåŠçããWebã³ã³ããŒãã³ããèããŠã¿ãŸããããããã¯ãã°ããŒãã«ãªãªãŒãã£ãšã³ã¹ã察象ãšããã¢ããªã±ãŒã·ã§ã³ã«ãšã£ãŠéåžžã«éèŠã§ãã
i18n-component.js
class I18nComponent extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: 'open' });
this.language = 'en'; // Default language
this.translations = {
en: {
greeting: 'Hello, world!',
buttonText: 'Click me',
},
fr: {
greeting: 'Bonjour le monde !',
buttonText: 'Cliquez ici',
},
es: {
greeting: '¡Hola Mundo!',
buttonText: 'Haz clic aquÃ',
},
};
this.render();
}
setLanguage(lang) {
this.language = lang;
this.render();
}
render() {
const translation = this.translations[this.language] || this.translations['en']; // Fallback to English
this.shadow.innerHTML = `
<p>${translation.greeting}</p>
<button>${translation.buttonText}</button>
`;
}
}
customElements.define('i18n-component', I18nComponent);
i18n-component.test.js (Jest)
import './i18n-component.js';
describe('I18nComponent', () => {
let element;
beforeEach(() => {
element = document.createElement('i18n-component');
document.body.appendChild(element);
});
afterEach(() => {
document.body.removeChild(element);
});
it('should display the English greeting by default', () => {
expect(element.shadowRoot.querySelector('p').textContent).toBe('Hello, world!');
});
it('should display the French greeting when the language is set to fr', () => {
element.setLanguage('fr');
expect(element.shadowRoot.querySelector('p').textContent).toBe('Bonjour le monde !');
});
it('should display the Spanish greeting when the language is set to es', () => {
element.setLanguage('es');
expect(element.shadowRoot.querySelector('p').textContent).toBe('¡Hola Mundo!');
});
it('should fallback to English if the language is not supported', () => {
element.setLanguage('de'); // German is not supported
expect(element.shadowRoot.querySelector('p').textContent).toBe('Hello, world!');
});
});
ãã®äŸã¯ãåœéåã³ã³ããŒãã³ãããŠããããã¹ãããæ¹æ³ã瀺ããŠãããéžæãããèšèªã«åºã¥ããŠæ£ããããã¹ãã衚瀺ãããå¿ èŠã«å¿ããŠããã©ã«ãèšèªã«ãã©ãŒã«ããã¯ããããšã確èªããŸãããã®ã³ã³ããŒãã³ãã¯ãWebéçºã«ãããŠã°ããŒãã«ãªãªãŒãã£ãšã³ã¹ãèæ ®ããããšã®éèŠæ§ã瀺ããŠããŸãã
Webã³ã³ããŒãã³ãã®ã¢ã¯ã»ã·ããªãã£ãã¹ã
Webã³ã³ããŒãã³ããé害ãæã€ãŠãŒã¶ãŒã«ãšã£ãŠã¢ã¯ã»ã¹å¯èœã§ããããšãä¿èšŒããããšã¯éåžžã«éèŠã§ããã¢ã¯ã»ã·ããªãã£ãã¹ãã¯ããã¹ãã¯ãŒã¯ãããŒã«çµ±åãããã¹ãã§ãã
ã¢ã¯ã»ã·ããªãã£ãã¹ãçšã®ããŒã«ïŒ
- axe-coreïŒ ãªãŒãã³ãœãŒã¹ã®ã¢ã¯ã»ã·ããªãã£ãã¹ããšã³ãžã³ã§ãã
- LighthouseïŒ ã¢ã¯ã»ã·ããªãã£ãå«ãWebããŒãžãç£æ»ããããã®Google Chromeæ¡åŒµæ©èœããã³Node.jsã¢ãžã¥ãŒã«ã§ãã
äŸïŒaxe-coreãšJestã䜿çšããã¢ã¯ã»ã·ããªãã£ãã¹ã
import { axe, toHaveNoViolations } from 'jest-axe';
import './my-component.js';
expect.extend(toHaveNoViolations);
describe('MyComponent Accessibility', () => {
let element;
beforeEach(async () => {
element = document.createElement('my-component');
document.body.appendChild(element);
await element.updateComplete; // Wait for the component to render
});
afterEach(() => {
document.body.removeChild(element);
});
it('should pass accessibility checks', async () => {
const results = await axe(element.shadowRoot);
expect(results).toHaveNoViolations();
});
});
ãã®äŸã¯ãaxe-coreãšJestã䜿çšããŠWebã³ã³ããŒãã³ãã§èªåã¢ã¯ã»ã·ããªãã£ãã¹ããå®è¡ããæ¹æ³ã瀺ããŠããŸãã`toHaveNoViolations`ã¯ãã³ã³ããŒãã³ãã«ã¢ã¯ã»ã·ããªãã£éåããªãããšãã¢ãµãŒãããã«ã¹ã¿ã Jestãããã£ãŒã§ããããã«ãããWebã¢ããªã±ãŒã·ã§ã³ã®å æ¬æ§ãå€§å¹ ã«åäžããŸãã
çµè«
Webã³ã³ããŒãã³ãã®ãã¹ãã¯ãå ç¢ã§ä¿å®å¯èœããã€åå©çšå¯èœãªUIèŠçŽ ãæ§ç¯ããããã«äžå¯æ¬ ã§ãããŠããããã¹ããšã³ã³ããŒãã³ãåé¢ãã¹ãã¯ãã³ã³ããŒãã³ãã®å質ãä¿èšŒããäžã§éèŠãªåœ¹å²ãæãããŸãããããã®æŠç¥ãçµã¿åããããã¹ããã©ã¯ãã£ã¹ã«åŸãããšã§ãä¿¡é Œæ§ãé«ããã¢ã¯ã»ã¹ãããããã°ããŒãã«ãªãªãŒãã£ãšã³ã¹ã«çŽ æŽããããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãæäŸããWebã³ã³ããŒãã³ããäœæã§ããŸããã³ã³ããŒãã³ããå æ¬çã§ããåºããªãŒãã£ãšã³ã¹ã«å±ãããã«ããã¹ãããã»ã¹ã§åœéåãšã¢ã¯ã»ã·ããªãã£ã®åŽé¢ãèæ ®ããããšãå¿ããªãã§ãã ããã