use lib 'lib';
use lib 'specs/support';
use BDD::Behave;
use BloginTest;
use Blogin::Layout;
use Blogin::Site;
use Blogin::Config;

describe 'the fragment cache memoizes invariant chrome', {
  before-each { Blogin::Layout::clear-fragment-cache() }

  it 'runs the block only once for a repeated key', {
    my $calls = 0;
    View.new.cache-fragment('side', { $calls++; 'html' });
    View.new.cache-fragment('side', { $calls++; 'html' });
    expect($calls).to.eq(1);
  }

  it 'returns the first render on every later call', {
    View.new.cache-fragment('key', { 'first' });
    expect(View.new.cache-fragment('key', { 'second' })).to.eq('first');
  }

  it 'keeps distinct keys independent', {
    my $calls = 0;
    View.new.cache-fragment('a', { $calls++; 'A' });
    View.new.cache-fragment('b', { $calls++; 'B' });
    expect($calls).to.eq(2);
  }

  it 'renders again after the cache is cleared', {
    my $calls = 0;
    View.new.cache-fragment('key', { $calls++; 'X' });
    Blogin::Layout::clear-fragment-cache();
    View.new.cache-fragment('key', { $calls++; 'X' });
    expect($calls).to.eq(2);
  }
}

describe 'a layout caches a partial across pages', {
  let(:proj, { temp-made('fragproj') });

  before-each {
    proj().add('content/posts').mkdir;
    proj().add('content/posts/2026-07-01-a.md').spurt("---\ntitle: A\ndate: 2026-07-01\n---\nbody a\n");
    proj().add('content/posts/2026-07-02-b.md').spurt("---\ntitle: B\ndate: 2026-07-02\n---\nbody b\n");

    my $layouts = proj().add('layouts');
    $layouts.mkdir;

    $layouts.add('base.haml').spurt(q:to/HAML/);
    %html
      %body
        != cache-fragment('chrome', { render(:partial<chrome>) })
        = yield
    HAML

    $layouts.add('_chrome.haml').spurt("%footer chrome-here\n");
    $layouts.add('show.haml').spurt("%h1= title\n");
    $layouts.add('index.haml').spurt("%section= heading\n");

    Blogin::Site::build(
      content => proj().add('content'),
      out     => proj().add('public'),
      layouts => $layouts,
    );
  }

  after-each { nuke(proj()) }

  it 'renders the cached partial on the first post', {
    expect(proj().add('public/posts/a.html').slurp.contains('<footer>chrome-here</footer>')).to.be-truthy;
  }

  it 'renders the same cached partial on the second post', {
    expect(proj().add('public/posts/b.html').slurp.contains('<footer>chrome-here</footer>')).to.be-truthy;
  }
}
