참고소스 수정본

This commit is contained in:
LASTA_DEV01\lasta
2026-05-12 19:40:31 +09:00
parent 0f34a451fc
commit 2e9204243d
8708 changed files with 3259488 additions and 869 deletions

View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2014 Guille Paz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,25 @@
# Battery Status API
> Battery Status API Demo
## Demo
http://pazguille.github.io/demo-battery-api/
## Support
- Chrome 38+
- Chrome for Android
- Firefox 31+
## Specs
http://www.w3.org/TR/battery-status
## Maintained by
- Guille Paz (Frontender & Web standards lover)
- E-mail: [guille87paz@gmail.com](mailto:guille87paz@gmail.com)
- Twitter: [@pazguille](http://twitter.com/pazguille)
- Web: [http://pazguille.me](http://pazguille.me)
## License
Licensed under the MIT license.
Copyright (c) 2014 [@pazguille](http://twitter.com/pazguille).

View File

@@ -0,0 +1,51 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Battery Status API - Demo</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta http-equiv="cleartype" content="on">
<meta name="HandheldFriendly" content="True">
<link rel="stylesheet" href="src/styles.css">
</head>
<body>
<header class="demo-header">
<h1 class="demo-title">Battery Status API</h1>
<p class="not-support" hidden>Your browser doesn't support the Battery Status API :(</p>
</header>
<article class="battery-card">
<h1 class="battery-title">Battery Status</h1>
<div class="battery-box">
<strong class="battery-percentage"></strong>
<i class="battery"></i>
</div>
<dl class="battery-info">
<dt>Power Source</dt>
<dd class="battery-status">---</dd>
<dt>Level percentage</dt>
<dd class="battery-level">---</dd>
<dt>Fully charged in</dt>
<dd class="battery-fully">---</dd>
<dt>Remaining time</dt>
<dd class="battery-remaining">---</dd>
</dl>
</article>
<footer>
<a href="https://github.com/pazguille/demo-battery-api" id="github-ribbon"><img width="149" height="149" src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub"></a>
by <a href="http://pazguille.me/">Guille Paz</a> with <span class="heart"></span>
<iframe id="github-button" src="https://ghbtns.com/github-btn.html?user=pazguille&amp;repo=demo-battery-api&amp;type=watch&amp;count=true" allowtransparency="true" frameborder="0" scrolling="0" width="152" height="30"></iframe>
</footer>
<script src="src/index.js" async></script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

View File

@@ -0,0 +1,71 @@
(function() {
'use strict';
var battery;
function toTime(sec) {
sec = parseInt(sec, 10);
var hours = Math.floor(sec / 3600),
minutes = Math.floor((sec - (hours * 3600)) / 60),
seconds = sec - (hours * 3600) - (minutes * 60);
if (hours < 10) { hours = '0' + hours; }
if (minutes < 10) { minutes = '0' + minutes; }
if (seconds < 10) { seconds = '0' + seconds; }
return hours + ':' + minutes;
}
function readBattery(b) {
battery = b || battery;
var percentage = parseFloat((battery.level * 100).toFixed(2)) + '%',
fully,
remaining;
if (battery.charging && battery.chargingTime === Infinity) {
fully = 'Calculating...';
} else if (battery.chargingTime !== Infinity) {
fully = toTime(battery.chargingTime);
} else {
fully = '---';
}
if (!battery.charging && battery.dischargingTime === Infinity) {
remaining = 'Calculating...';
} else if (battery.dischargingTime !== Infinity) {
remaining = toTime(battery.dischargingTime);
} else {
remaining = '---';
}
document.styleSheets[0].insertRule('.battery:before{width:' + percentage + '}', 0);
document.querySelector('.battery-percentage').innerHTML = percentage;
document.querySelector('.battery-status').innerHTML = battery.charging ? 'Adapter' : 'Battery';
document.querySelector('.battery-level').innerHTML = percentage;
document.querySelector('.battery-fully').innerHTML = fully;
document.querySelector('.battery-remaining').innerHTML = remaining;
}
if (navigator.battery) {
readBattery(navigator.battery);
} else if (navigator.getBattery) {
navigator.getBattery().then(readBattery);
} else {
document.querySelector('.not-support').removeAttribute('hidden');
}
window.onload = function () {
battery.addEventListener('chargingchange', function() {
readBattery();
});
battery.addEventListener("levelchange", function() {
readBattery();
});
};
}());

View File

@@ -0,0 +1,156 @@
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}
/**
* Mobile First
*/
body {
font: 100%/1.4em "Helvetica Neue", "Helvetica", "Arial", sans-serif;
margin: 0 auto;
padding: 0 0.625em;
color: #444;
-webkit-text-size-adjust: none;
}
/**
* Small Screens
*/
.demo-header {
margin-bottom: 80px;
text-align: center;
}
.demo-title {
font-size: 4em;
line-height: 1em;
text-align: center;
}
.battery-card {
font-family: "Helvetica", Arial, sans-serif;
display: block;
width: 300px;
overflow: hidden;
border: 1px solid #D5D5D5;
border-radius: 6px;
font-weight: 100;
margin: 0 auto;
}
.battery-title {
background: #4c4c4c url('bolt.png') no-repeat 95% 15px;
color: #fff;
font-size: .9em;
line-height: 50px;
padding: 0 15px;
font-weight: 100;
margin: 0;
}
.battery-percentage {
font-size: 2.5em;
line-height: 50px;
display: inline-block;
vertical-align: middle;
margin-right: 10px;
}
.battery-box {
margin: 0 auto;
padding: 50px 0;
text-align: center;
border-bottom: 1px solid #D5D5D5;
}
.battery {
display: inline-block;
position: relative;
border: 4px solid #000;
width: 85px;
height: 40px;
border-radius: 4px;
vertical-align: middle;
}
.battery:before {
content: '';
display: block;
box-sizing: border-box;
background: #000;
height: 40px;
position: absolute;
border: 1px solid #fff;
}
.battery:after {
content: '';
display: block;
background: #000;
width: 6px;
height: 16px;
position: absolute;
top: 50%;
right: -11px;
margin-top: -8px;
border-radius: 0 4px 4px 0;
}
.battery-info {
font-size: 12px;
margin: 0 auto;
padding: 15px 45px;
overflow: hidden;
}
.battery-info dd {
float: right;
margin-top: -22px;
text-align: left;
width: 35%;
}
footer {
margin: 70px auto 0;
text-align: center;
}
.heart {
font-style: normal;
font-weight: 500;
color: #c0392b;
text-decoration: none;
}
#github-button {
display: block;
margin: 30px auto 0;
position: relative;
left: 40px;
}
#github-ribbon {
display: inline-block;
position: fixed;
top: 0;
right: 0;
z-index: 100;
border: 0;
width: 149px;
height: 149px;
}
.github-buttons {
text-align: center;
margin: 1em 0;
}
/**
* Medium Screens
*/
@media all and (min-width:40em) {}
/**
* Large Screens
*/
@media all and (min-width: 54em) {}

View File

@@ -0,0 +1,17 @@
{
"name": "mock-battery",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "playwright test",
"start": "http-server -c-1 -p 9900 demo-battery-api"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@playwright/test": "^1.19.1",
"http-server": "^14.1.0"
}
}

View File

@@ -0,0 +1,13 @@
// @ts-check
const path = require('path')
const { defineConfig } = require('@playwright/test');
module.exports = defineConfig({
webServer: {
port: 9900,
command: 'npm run start',
},
// Test directory
testDir: path.join(__dirname, 'tests'),
});

View File

@@ -0,0 +1,26 @@
// @ts-check
const { test, expect } = require('@playwright/test');
test.beforeEach(async ({ page }) => {
await page.addInitScript(() => {
const mockBattery = {
level: 0.90,
charging: true,
chargingTime: 1800, // seconds
dischargingTime: Infinity,
addEventListener: () => { }
};
// application tries navigator.battery first
// so we delete this method
delete window.navigator.battery;
// Override the method to always return mock battery info.
window.navigator.getBattery = async () => mockBattery;
});
});
test('show battery status', async ({ page }) => {
await page.goto('/');
await expect(page.locator('.battery-percentage')).toHaveText('90%');
await expect(page.locator('.battery-status')).toHaveText('Adapter');
await expect(page.locator('.battery-fully')).toHaveText('00:30');
})

View File

@@ -0,0 +1,81 @@
// @ts-check
const { test, expect } = require('@playwright/test');
let log = [];
test.beforeEach(async ({page}) => {
log = [];
// Expose function for pushing messages to the Node.js script.
await page.exposeFunction('logCall', msg => log.push(msg));
await page.addInitScript(() => {
// for these tests, return the same mock battery status
class BatteryMock {
level = 0.10;
charging = false;
chargingTime = 1800;
dischargingTime = Infinity;
_chargingListeners = [];
_levelListeners = [];
addEventListener(eventName, listener) {
logCall(`addEventListener:${eventName}`);
if (eventName === 'chargingchange')
this._chargingListeners.push(listener);
if (eventName === 'levelchange')
this._levelListeners.push(listener);
}
_setLevel(value) {
this.level = value;
this._levelListeners.forEach(cb => cb());
}
_setCharging(value) {
this.charging = value;
this._chargingListeners.forEach(cb => cb());
}
};
const mockBattery = new BatteryMock();
// Override the method to always return mock battery info.
window.navigator.getBattery = async () => {
logCall('getBattery');
return mockBattery;
};
// Save the mock object on window for easier access.
window.mockBattery = mockBattery;
// application tries navigator.battery first
// so we delete this method
delete window.navigator.battery;
});
});
test('should update UI when battery status changes', async ({ page }) => {
await page.goto('/');
await expect(page.locator('.battery-percentage')).toHaveText('10%');
// Update level to 27.5%
await page.evaluate(() => window.mockBattery._setLevel(0.275));
await expect(page.locator('.battery-percentage')).toHaveText('27.5%');
await expect(page.locator('.battery-status')).toHaveText('Battery');
// Emulate connected adapter
await page.evaluate(() => window.mockBattery._setCharging(true));
await expect(page.locator('.battery-status')).toHaveText('Adapter');
await expect(page.locator('.battery-fully')).toHaveText('00:30');
});
test('verify API calls', async ({ page }) => {
await page.goto('/');
await expect(page.locator('.battery-percentage')).toHaveText('10%');
// Ensure expected method calls were made.
expect(log).toEqual([
'getBattery',
'addEventListener:chargingchange',
'addEventListener:levelchange'
]);
log = []; // reset the log
await page.evaluate(() => window.mockBattery._setLevel(0.275));
expect(log).toEqual([]); // getBattery is not called, cached version is used.
});

View File

@@ -0,0 +1,39 @@
// @ts-check
const { test, expect } = require('@playwright/test');
let log = [];
test.beforeEach(async ({page}) => {
log = [];
// Expose function for pushing messages to the Node.js script.
await page.exposeFunction('logCall', msg => log.push(msg));
await page.addInitScript(() => {
const mockBattery = {
level: 0.75,
charging: true,
chargingTime: 1800, // seconds
dischargingTime: Infinity,
addEventListener: (name, cb) => logCall(`addEventListener:${name}`)
};
// Override the method to always return mock battery info.
window.navigator.getBattery = async () => {
logCall('getBattery');
return mockBattery;
};
// application tries navigator.battery first
// so we delete this method
delete window.navigator.battery;
});
})
test('verify battery calls', async ({ page }) => {
await page.goto('/');
await expect(page.locator('.battery-percentage')).toHaveText('75%');
// Ensure expected method calls were made.
expect(log).toEqual([
'getBattery',
'addEventListener:chargingchange',
'addEventListener:levelchange'
]);
});