Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
karmaを使ったSPA向けE2Eテスト技法
Search
kyo_ago
February 27, 2017
Programming
5.8k
6
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
karmaを使ったSPA向けE2Eテスト技法
kyo_ago
February 27, 2017
More Decks by kyo_ago
See All by kyo_ago
フロントエンドの リソース管理の話 TechFeed Summit#1 #techfeed #techfeedsummit
kyo_ago
5
2k
TypeScriptでType Match的なことをする話 #すえなみチャンス暑気払い
kyo_ago
1
1.4k
WebReplayから見るWeb開発の未来 #builderscon
kyo_ago
2
1k
今日から始めるbugbounty
kyo_ago
0
320
E2Eという名称の指すもの
kyo_ago
0
2.7k
How to use Scala.js in real world?
kyo_ago
1
2.2k
Other Decks in Programming
See All in Programming
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
550
R8 の設定見直しでアプリサイズ削減
andpad
0
180
ハーネス設計入門 〜 基礎知識の整理から実務へのステップアップ 〜
kinopeee
20
21k
難しいけど、読めた。- OSSの入口に立った話。
sts11142
0
140
RAG の “R” を Swift で覗いてみる 〜「意味から探す」検索の仕組み〜
nao_randd
0
120
Embedded Swiftで作る自作USBデバイス によるiOSデバイスの自動テスト / iOSDC Japan 2026 glassfiber
glassfiber
0
300
GitHubハンズオン講座 — 実務レベルのチーム開発のフローを身につけよう
junhat6
0
120
大喜利で理解するLLM as a Judge / Understanding LLM-as-a-Judge through Ogiri
rockname
0
190
なぜCTOを降りてFDEを選んだのか?〜なぜプロダクト企業がFDEで顧客の現場に踏み込むのか〜
gonta
1
160
Domain-Driven Transformation
hschwentner
2
2.3k
Apple Intelligence を用いた個人情報誤送信防止、及びユーザーリクエスト体験の改善について
yukiny
0
310
[2026-09-26]空論ジェネリックプロセス~テスト資産とAIで紡ぐ、再現可能なパフォーマンスチューニングの話~
tosite
0
260
Featured
See All Featured
Navigating Team Friction
lara
192
16k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
460
Navigating Weather and Climate Data
rabernat
0
550
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.5k
Agile that works and the tools we love
rasmusluckow
331
22k
Unsuck your backbone
ammeep
672
58k
Ten Tips & Tricks for a 🌱 transition
stuffmc
1
250
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
1.1k
Exploring anti-patterns in Rails
aemeredith
4
520
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
How Software Deployment tools have changed in the past 20 years
geshan
2
35k
Transcript
karmaΛͬͨSPA͚ E2Eςετٕ๏
ࣗݾհ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ ɾ@kyo_ago ɾChatworkͷதͷਓ ɾझຯLocal Proxy࡞ ɾUnder30͡Όͳ͍ΤϯδχΞ ɾਪ͠APIApplication Cache
·ͣँࡑ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ࠓճ௨Γ͕͍͍ͱࢥͬͯʮ&&ςετʯͬͯݴͬͯ·͕͢ *OUFHSBUJPOςετͬͯݴ͏ํ͕ਖ਼֬ͩͬͨΓ͠·͢ɻ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ࠓճ͍͑ͨ͜ͱ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
41"ͷςετʹ 8FC%SJWFS͔ͳ͍ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
8FC%SJWFSͱ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
4FMFOJVN͔Βൃలͨ͠πʔϧ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ϒϥβ͝ͱͷυϥΠόͱ ͦͷυϥΠόͱ௨৴͢Δ"1* LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ ChromeDriver FirefoxDriver IEDriver SafariDriver JSON Wire Protocol
"1*ʹରԠͨ͠ΫϥΠΞϯτΛ ͏͜ͱͰ൚༻తͳςετ͕Ͱ ͖Δ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ྺ࢙͋Δ&&ςετͷ మ൘πʔϧ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ 2004։ൃ։࢝
Ͱͳͥʮ41"ͷςετʹ 8FC%SJWFS͔ͳ͍ʯͷ͔ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
8FC%SJWFS͋͘·Ͱը໘ ΛભҠ͍ͯ͘͠ʮ8FCαΠτʯ ͷͨΊͷςετπʔϧ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
41"͚ͷςετπʔϧͰͳ ͍ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
41"Λ8FC%SJWFSͰςετ͢ Δͷ͍͠ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
8FC%SJWFS௨ৗͷ։ൃπʔ ϧͱҧ͏֓೦Ͱಈ͘ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ ChromeDriver FirefoxDriver IEDriver SafariDriver JSON Wire Protocol ಠࣗϓϩτίϧͷੈք
௨ৗͷ։ൃϑϩʔͱͷ ࠩҟ͕େ͖͍ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ྫ͑ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
/PEFDPOUFYUͱ #SPXTFSDPOUFYUͷஅ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ Electron͕ղܾ͔ͨͬͨͭ͠
let webdriver = require('selenium-webdriver'); let driver = new webdriver.Builder()
.forBrowser('chrome') .build(); driver.executeScript('return 2').then((res) => { console.log('returned ', res); }); driver.get('https://www.google.co.jp/').then(() => { driver.quit(); }); LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ ͚ͩ͜͜#SPXTFSDPOUFYU
%FWFMPQQFS5PPMTͱڝ߹ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ DriverʹΑͬͯ
DPOTPMFMPHͷ༰͕UFSNJOBM Ͱ͔֬͠ೝͰ͖ͳ͍ ʢ0CKFDUల։ͱ͔ग़དྷͳ͍ʣ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
OPEFJOEFYKT UIFOBCMF8FC%SJWFS1SPYZ\ qPX@ $POUSPM'MPX\ QSPQBHBUF6OIBOEMFE3FKFDUJPOT@USVF BDUJWF2VFVF@ 5BTL2VFVF\ OBNF@5BTL2VFVF
qPX@<$JSDVMBS> UBTLT@<0CKFDU> JOUFSSVQUT@OVMM QFOEJOH@OVMM TVC2@OVMM LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ ͜Ε͕ਏ͍ʂ
ը໘ΛભҠ͍ͯ͘͠ʮ8FCα ΠτʯͰ͋ΕͦΕ΄Ͳͳ ͍ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
41"ͷ߹ɺ͜ΕΒͷπʔϧ͕ ͑ͳ͍ͷඇৗʹ͍͠ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
·ͨɺ8FC%SJWFSϖʔδͷ ಡΈࠐΈΫϦοΫޙͷભҠΛ ࣗಈͰͭػೳ͕͋Δ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
var webdriver = require('selenium-webdriver'), By = webdriver.By, until = webdriver.until;
var driver = new webdriver.Builder() .forBrowser('firefox') .build(); driver.get('http://www.google.com/'); driver.findElement(By.name(‘q')).sendKeys('webdriver'); driver.findElement(By.name('btnG')).click(); driver.wait(until.titleIs('webdriver - Google Search'), 1000); driver.quit(); LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ ͬͯ͘ΕΔ
͕ɺ41"Ͱ௨ৗ͜ΕΒͷػೳ ༻͠ͳ͍ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ͦ͜Ͱ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
41"ͷ*OUFHSBUJPOςετʹ ,BSNB LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
,BSNB LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ɾɾɾͬͯ͠·͢ʁ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ࣾͰฉ͍ͯΈͨ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ʮLBSNBͷ͢ΔΜͰ͢Αʯ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ʮ͋Εɺ"OHVMBS+4ઐ༻Ͱ͢Α Ͷʁʯ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ʮ·ͩ͋ͬͨΜͰ͔͢ʁʯ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ʮ1SPUSBDUPSʹͳͬͨͱࢥͬ ͯ·ͨ͠ʯ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ɾɾɾ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ͱͱ"OHVMBS+4ͷςετ༻ ʹ։ൃ͞Εͨςετπʔϧ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ݱࡏී௨ʹ൚༻తͳπʔϧ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ ʢͱݴ͏͔Ή͠ΖAngularͱͷ૬ੑྑ͘ͳ͍Α͏ͳɻɻɻʣ
·ͩ·ͩ։ൃ׆ൃ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ ʢ5લʹver 1.5.0ެ։ʣ
1SPUSBDUPSͱҧ͏ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ ʢProtractorWebDriverܥʣ
ͬ͘͟Γ͍͏ͱ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ϒϥβ্Ͱಈ͘ 6OJUςετϥϯφʔ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
describe('Assert', () => { it('should true', () => { expect(true).toEqual(true);
}); }); LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ ͜Ε͕ϒϥβ্Ͱಈ͘
ࠓճ7FSͰՃ͞Εͨ ػೳΛͬͯ*OUFHSBUJPOςε τͷํΛհ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
DVTUPN$POUFYU'JMF LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ςετΛࢦఆ͞ΕͨIUNM্Ͱ ߦ͏ػೳ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
<!DOCTYPE html> <html lang="ja"> <head> <script src="context.js"></script> <script type="text/javascript"> %CLIENT_CONFIG%
window.__karma__.setupContext(window); %MAPPINGS% </script> %SCRIPTS% <title>Inside Frontend</title> </head> <body> <script type="text/javascript"> window.__karma__.loaded(); </script> </body> </html> LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ ͜͜ʹLBSNBDPOGKTͷ'JMF͕ల։͞ΕΔ ͔͜͜Β࣮ߦΛ։࢝
·ΔͰαΠτ্Ͱ6OJUUFTUΛ Β͍ͤͯΔ͔ͷΑ͏ʹॻ͚Δ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
describe('Document title', () => { it('should be', () => {
expect(document.title).toEqual('Inside Frontend'); }); }); LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
Β͍͘ʂ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
͔͠͠ɻɻɻ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
DVTUPN$POUFYU'JMFʹ Γͳ͋͞Δ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
Γͳ͞ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ಡΈࠐΈॴ͕MPDBMIPTU LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ Γͳ͞
࣮ࡍςετ͍ͨ͠υϝΠϯͰಡ Έࠐ·ΕΔΘ͚Ͱͳ͍ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ ͜͏͍ͨ͠
ௐͯΈͨ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ɻɻɻͪΐͬͱແཧͬΆ͍ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ ͜͏͢Δ
LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ผυϝΠϯ௨৴ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ϒϥβΛͩ·͢ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
खॱ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
௨৴ͷॻ͖͑ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
-PDBMQSPYZΛ͏ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
$ npm install --save-dev karma-proxy-plugin LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
customContextFile: "custom-context-file.html", proxyValidateSSL: false, client: { clearContext: false }, middleware:
['proxy'], proxy: { '/inside-frontend/': { 'target': 'http://inside-frontend.com/', 'changeOrigin': true } }, proxyReq: (proxyReq, req, res, options) => { }, proxyRes: (proxyRes) => { }, LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ LBSNBDPOGKT 44-1SPYZ࣌ͷূ໌ॻΤϥʔΛແࢹ ςετ࣮ߦ͝ͱʹڥΛΫϦΞ͠ͳ͍ LBSNBQSPYZQMVHJO༻ LBSNBඪ४ͷQSPYJFTͰͳ͍͜ͱʹҙ ૹ৴Πϕϯτ ड৴Πϕϯτ
JOTJEFGSPOUFOEͷ௨৴Λ IUUQJOTJEFGSPOUFOEDPN సૹ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
௨৴ͷ͖ઌͷมߋ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
IUNM+4ͷ௨৴ͷ͖ઌΛ JOTJEFGSPOUFOEʹ͚͍ͨ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ 1ͰProxyϓϩηε্ཱ͕͕͚ͪͬͨͩͰɺ ϒϥβͷProxyઃఆΛߦͬͨΘ͚Ͱͳ͍
let base = document.createElement('base'); base.href = '/example/'; document.head.insertAdjacentElement('afterbegin', base); LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
DVTUPNDPOUFYUpMFIUNM
XMLHttpRequest = () => {/* … */}; fetch = ()
=> {/* … */}; LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ DVTUPNDPOUFYUpMFIUNM
؆୯ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ଞʹ͍Ζ͍Ζ͍ͨ͠߹ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
3FGFSFSΛॻ͖͍͑ͨ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
proxyReq: (proxyReq, req, res, options) => { proxyReq.setHeader('Referer', 'https://example.com/'); },
LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ LBSNBDPOGKT
$PPLJFΛॻ͖͍͑ͨ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
proxyRes: (proxyRes) => { if (proxyRes.headers['set-cookie']) { proxyRes.headers['set-cookie'] = proxyRes.headers['set-cookie'].map((cookie)
=> { // karmahttpͳͷͰsecureΛফ͢ return cookie.replace(/\s*secure;?/i, ''); }) } }, LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ LBSNBDPOGKT
ϦμΠϨΫτઌΛมߋ͍ͨ͠ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
proxyRes: (proxyRes) => { if (proxyRes.headers['location']) { // ϦμΠϨΫτઌΛมߋ proxyRes.headers['location']
= proxyRes.headers['location'].replace(/^https:\/\/ example.com/i, '/example/'); } }, LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ LBSNBDPOGKT
ϩάΠϯ͍ͨ͠ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
fetch('/example/login', { method: 'POST', body: new FormData(document.getElementById('#login')) }).then((response) => response.text()).then((text)
=> { // ϨεϙϯεʹToken͕͋Εมʹอଘ // Cookieอ࣋͞ΕΔ window.__karma__.loaded(); }); LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ DVTUPNDPOUFYUpMFIUNM
͜͏͍ͬͨํ๏Λ͏͜ͱͰผ υϝΠϯͰಡΈࠐ·ΕΔΛ ղফ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
QSPYZ3FRɺQSPYZ3FTͷҾ ҎԼࢀর LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ IUUQTHJUIVCDPNOPEFKJUTVOPEFIUUQQSPYZ
͜͜·ͰདྷΔͱςετΛॻ͘ͷ ඇৗʹ؆୯ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ී௨ʹαΠτ্ͷ%FW5PPMT্ Ͱݕূ͢ΔͷͱมΘΒͳ͍Ϩϕ ϧͰςετ͕ॻ͚Δ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ const assert = require("power-assert"); describe('index page', () =>
{ it('Google map', () => { assert(google.maps); }); it('copyright', () => { assert(document.querySelector('.copyright')); }); });
ඇৗʹ͓͢͢Ί LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
࣮ࡍͬͯΈͯͲ͏͔ͩͬͨ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ςετඇৗʹॻ͖͍͢ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ͨͩɺϒϥβʹىҼ͢Δෆ҆ ఆ͞Ͳ͏͠Α͏ͳ͔ͬͨ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
%0.ͱ͍͏Ҭม͍ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ঢ়ଶͷΫϦΞ͕ࣗͷʹͳ ΔͷͰਏ͍ ʢָʹͳΔ෦͋Δ͚Ͳʣ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ࣗͰ੍ޚͰ͖Δൣғ͕͕Δ ͷخ͍͠ ʢ8FC%SJWFSͷϒϥοΫϘο Ϋεײ͕ͳ͍ʣ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ͦͦ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
8FC%SJWFSड͚ೖΕςετ ͷπʔϧͰ͋ͬͯɺ։ൃऀ͚ πʔϧͰͳ͍ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
։ൃ͠ͳ͕Βςετ͢ΔͷͰ͋ Εผͷํ๏Λݕ౼͢Δํ͕͍ ͍ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
ͨͩɺड͚ೖΕςετͳΒ 8FC%SJWFSͷ΄͏͕ྑ͍͔ ͠Εͳ͍ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
8FC%SJWFSߴੑೳ͚ͩͲɺ ෆཁͳػೳଟ͍ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
࠷ޙʹ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
&&ςετ ॻ͔ͳ͍ʹӽͨ͜͠ͱͳ͍ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
࣭͝ʁ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏
࣭͝ʁ LBSNBΛͬͨ41"͚ͷ&&ςετٕ๏ ྫ ɾ࣮ߦ࣌ؒʁ ɾ࣮ࡍͲ͏͍͏;͏ʹಈ͔ͯ͠Δʁ ɾଞͷϝϯόʔͷԠʁ ɾͬͯΑ͔ͬͨʁ ɾͲ͏͍͏ͱ͖ʹ͓͢͢Ίʁ ɾCIͱͷ࿈ܞʁ