import textwrap

# === shorten: text fits within width ===
assert textwrap.shorten('Hello World', 12, placeholder='[...]') == 'Hello World', 'shorten fits'
assert textwrap.shorten('Hello World', 11, placeholder='[...]') == 'Hello World', 'shorten exact fit'
assert textwrap.shorten('abc', 10, placeholder='[...]') == 'abc', 'shorten short text'
assert textwrap.shorten('', 10, placeholder='[...]') == '', 'shorten empty string'

# === shorten: text truncated ===
assert textwrap.shorten('Hello World', 10, placeholder='[...]') == 'Hello[...]', 'shorten truncated'
assert textwrap.shorten('Hello World', 5, placeholder='[...]') == '[...]', 'shorten placeholder only'

# === shorten: with custom placeholder ===
assert textwrap.shorten('Hello World', 10, placeholder='...') == 'Hello...', 'shorten custom placeholder'
assert textwrap.shorten('Hello World', 3, placeholder='...') == '...', 'shorten placeholder equals width'

# === shorten: whitespace collapsing ===
assert textwrap.shorten('  Hello   World  ', 11, placeholder='[...]') == 'Hello World', 'shorten collapses whitespace'

# === shorten: longer text ===
assert textwrap.shorten('The quick brown fox', 10, placeholder='[...]') == 'The[...]', 'shorten longer text'
assert textwrap.shorten('one two three', 10, placeholder='[...]') == 'one[...]', 'shorten word boundary'

# === TextWrapper: basic wrapping ===
wrapper = textwrap.TextWrapper(width=7)
assert wrapper.wrap('one two three') == ['one two', 'three'], 'TextWrapper.wrap should split on width'
assert wrapper.fill('one two three') == 'one two\nthree', 'TextWrapper.fill should join wrapped lines with newlines'

# === TextWrapper: indentation options ===
indented = textwrap.TextWrapper(width=9, initial_indent='> ', subsequent_indent='  ')
assert indented.wrap('one two three') == ['> one two', '  three'], 'TextWrapper should apply initial/subsequent indent'

# === TextWrapper: break_long_words ===
split_words = textwrap.TextWrapper(width=5, break_long_words=True)
assert split_words.wrap('abcdefgh') == ['abcde', 'fgh'], 'TextWrapper should split long words when enabled'

keep_words = textwrap.TextWrapper(width=5, break_long_words=False)
assert keep_words.wrap('abcdefgh') == ['abcdefgh'], 'TextWrapper should keep long words whole when disabled'

# === TextWrapper: exposed attributes ===
configured = textwrap.TextWrapper(
    width=12,
    initial_indent='>>',
    subsequent_indent='..',
    placeholder='***',
    max_lines=3,
    break_long_words=False,
)
assert configured.width == 12, 'TextWrapper.width should reflect constructor arg'
assert configured.initial_indent == '>>', 'TextWrapper.initial_indent should reflect constructor arg'
assert configured.subsequent_indent == '..', 'TextWrapper.subsequent_indent should reflect constructor arg'
assert configured.placeholder == '***', 'TextWrapper.placeholder should reflect constructor arg'
assert configured.max_lines == 3, 'TextWrapper.max_lines should reflect constructor arg'
