use super::*;
#[test]
fn get_computed_style_returns_live_values_and_property_aliases() -> Result<()> {
let html = r#"
<div id='box' style='color: blue; background-color: lime;'></div>
<button id='run'>run</button>
<p id='result'></p>
<script>
document.getElementById('run').addEventListener('click', () => {
const box = document.getElementById('box');
const styles = window.getComputedStyle(box);
const before = styles.getPropertyValue('color');
box.style.color = 'red';
const after = styles.getPropertyValue('color');
const alias = styles.color;
const camel = styles.backgroundColor;
const viaNullPseudo = window.getComputedStyle(box, null).getPropertyValue('color');
document.getElementById('result').textContent =
[before, after, alias, camel, viaNullPseudo].join(':');
});
</script>
"#;
let mut h = Harness::from_html(html)?;
h.click("#run")?;
h.assert_text("#result", "blue:red:red:lime:red")?;
Ok(())
}
#[test]
fn get_computed_style_supports_pseudo_argument_and_global_alias_chain() -> Result<()> {
let html = r#"
<style>
#box::after { content: " rocks!"; color: green; }
</style>
<div id='box' style='color: blue;'></div>
<button id='run'>run</button>
<p id='result'></p>
<script>
document.getElementById('run').addEventListener('click', () => {
const box = document.getElementById('box');
const pseudo = getComputedStyle(box, '::after');
const contentByMethod = pseudo.getPropertyValue('content');
const contentByProp = pseudo.content;
const pseudoColor = pseudo.getPropertyValue('color');
const elementColor = getComputedStyle(box).getPropertyValue('color');
document.getElementById('result').textContent =
[contentByMethod, contentByProp, pseudoColor, elementColor].join(':');
});
</script>
"#;
let mut h = Harness::from_html(html)?;
h.click("#run")?;
h.assert_text("#result", "\" rocks!\":\" rocks!\":green:blue")?;
Ok(())
}
#[test]
fn get_computed_style_rejects_invalid_target_and_pseudo_values() -> Result<()> {
let html = r#"
<div id='box' style='color: blue;'></div>
<button id='run'>run</button>
<p id='result'></p>
<script>
document.getElementById('run').addEventListener('click', () => {
const box = document.getElementById('box');
const checks = [];
try {
window.getComputedStyle(1);
checks.push('bad-target');
} catch (e) {
checks.push(String(e).includes('TypeError'));
}
try {
window.getComputedStyle(box, 'before');
checks.push('bad-pseudo');
} catch (e) {
checks.push(String(e).includes('pseudoElt'));
}
try {
window.getComputedStyle(box, '::part(tab)');
checks.push('bad-part');
} catch (e) {
checks.push(String(e).includes('pseudoElt'));
}
try {
window.getComputedStyle(box, 42);
checks.push('bad-type');
} catch (e) {
checks.push(String(e).includes('pseudoElt'));
}
document.getElementById('result').textContent = checks.join(':');
});
</script>
"#;
let mut h = Harness::from_html(html)?;
h.click("#run")?;
h.assert_text("#result", "true:true:true:true")?;
Ok(())
}
#[test]
fn computed_style_object_is_read_only() -> Result<()> {
let html = r#"
<div id='box' style='color: blue;'></div>
<button id='run'>run</button>
<p id='result'></p>
<script>
document.getElementById('run').addEventListener('click', () => {
const box = document.getElementById('box');
const styles = getComputedStyle(box);
let readOnly = false;
try {
styles.color = 'black';
} catch (e) {
readOnly = String(e).includes('read-only');
}
document.getElementById('result').textContent =
String(readOnly) + ':' + styles.getPropertyValue('color');
});
</script>
"#;
let mut h = Harness::from_html(html)?;
h.click("#run")?;
h.assert_text("#result", "true:blue")?;
Ok(())
}
#[test]
fn computed_style_exposes_item_and_live_alias_paths() -> Result<()> {
let html = r#"
<div id='box' style='background-color: lime;'></div>
<button id='run'>run</button>
<p id='result'></p>
<script>
document.getElementById('run').addEventListener('click', () => {
const box = document.getElementById('box');
const styles = getComputedStyle(box);
const before = [
typeof styles.item,
String(styles.item === styles.item),
styles.length,
styles.cssText,
String(styles.parentRule === null),
styles.item(0),
styles.item(1),
styles['background-color'],
styles.backgroundColor
].join(':');
box.style.backgroundColor = 'purple';
const after = [
styles.item(0),
styles['background-color'],
styles.backgroundColor
].join(':');
document.getElementById('result').textContent = [before, after].join('|');
});
</script>
"#;
let mut h = Harness::from_html(html)?;
h.click("#run")?;
h.assert_text(
"#result",
"function:true:0::true:::lime:lime|:purple:purple",
)?;
Ok(())
}
#[test]
fn reduced_computed_style_surface_is_live_readonly_and_non_copying_work() -> Result<()> {
let html = r#"
<div id='box' style='color: blue; background-color: lime;'></div>
<button id='run'>run</button>
<p id='result'></p>
<script>
document.getElementById('run').addEventListener('click', () => {
const box = document.getElementById('box');
const styles = getComputedStyle(box);
let readOnly = false;
try {
styles.color = 'black';
} catch (e) {
readOnly = String(e).includes('read-only');
}
const before = styles.color;
box.style.color = 'red';
const after = styles.color;
const own = Object.keys(styles).join(',');
const copied = Object.keys(Object.assign({}, styles)).join(',');
const spread = Object.keys({ ...styles }).join(',');
document.getElementById('result').textContent = [
String(readOnly),
before,
after,
String(styles.item === styles.item),
own,
copied,
spread
].join('|');
});
</script>
"#;
let mut h = Harness::from_html(html)?;
h.click("#run")?;
h.assert_text("#result", "true|blue|red|true|||")?;
Ok(())
}
#[test]
fn reduced_computed_style_surface_has_branded_non_enumerable_method_contract_work() -> Result<()> {
let html = r#"
<div id='box' style='color: blue;'></div>
<button id='run'>run</button>
<p id='result'></p>
<script>
document.getElementById('run').addEventListener('click', () => {
const styles = getComputedStyle(document.getElementById('box'));
const itemDesc = Object.getOwnPropertyDescriptor(styles, 'item');
const getDesc = Object.getOwnPropertyDescriptor(styles, 'getPropertyValue');
document.getElementById('result').textContent = [
Object.prototype.toString.call(styles),
styles[Symbol.toStringTag],
String(itemDesc.enumerable),
String(getDesc.enumerable),
typeof styles.item,
typeof styles.getPropertyValue
].join('|');
});
</script>
"#;
let mut h = Harness::from_html(html)?;
h.click("#run")?;
h.assert_text(
"#result",
"[object CSSStyleDeclaration]|CSSStyleDeclaration|false|false|function|function",
)?;
Ok(())
}