489 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			489 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
| # frozen_string_literal: true
 | |
| 
 | |
| # rubocop:disable Metrics/BlockLength
 | |
| require 'spec_helper'
 | |
| 
 | |
| describe(Jekyll::Algolia) do
 | |
|   let(:configurator) { Jekyll::Algolia::Configurator }
 | |
|   let(:current) { Jekyll::Algolia }
 | |
|   let(:extractor) { Jekyll::Algolia::Extractor }
 | |
|   let(:logger) { Jekyll::Algolia::Logger }
 | |
|   let(:file_browser) { Jekyll::Algolia::FileBrowser }
 | |
|   let(:progress_bar) { Jekyll::Algolia::ProgressBar }
 | |
|   let(:hooks) { Jekyll::Algolia::Hooks }
 | |
|   let(:indexer) { Jekyll::Algolia::Indexer }
 | |
| 
 | |
|   # Suppress Jekyll log about not having a config file
 | |
|   before do
 | |
|     allow(Jekyll.logger).to receive(:warn)
 | |
|     allow(logger).to receive(:log)
 | |
|   end
 | |
| 
 | |
|   describe '.init' do
 | |
|     let(:config) { Jekyll.configuration }
 | |
| 
 | |
|     context 'with valid Algolia credentials' do
 | |
|       subject { current.init(config) }
 | |
| 
 | |
|       before do
 | |
|         allow(configurator)
 | |
|           .to receive(:assert_valid_credentials)
 | |
|           .and_return(true)
 | |
|       end
 | |
| 
 | |
|       it 'should make the site accessible from the outside' do
 | |
|         expect(subject.site.config).to include(config)
 | |
|       end
 | |
|       it 'should check for deprecation warnings' do
 | |
|         expect(configurator).to receive(:warn_of_deprecated_options)
 | |
| 
 | |
|         current.init(config)
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'with invalid Algolia credentials' do
 | |
|       subject { -> { current.init(config) } }
 | |
|       before do
 | |
|         allow(configurator)
 | |
|           .to receive(:assert_valid_credentials)
 | |
|           .and_return(false)
 | |
|       end
 | |
| 
 | |
|       it { is_expected.to raise_error SystemExit }
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe 'overriding Jekyll::Site#process' do
 | |
|     let(:configuration) { Jekyll.configuration }
 | |
|     let(:jekyll_site) { Jekyll::Site.new(configuration) }
 | |
|     let(:algolia_site) { Jekyll::Algolia::Site.new(configuration) }
 | |
|     let!(:initial_method) { jekyll_site.method(:process).source_location }
 | |
|     let!(:overridden_method) { algolia_site.method(:process).source_location }
 | |
| 
 | |
|     before do
 | |
|       allow(algolia_site).to receive(:reset)
 | |
|       allow(algolia_site).to receive(:read)
 | |
|       allow(algolia_site).to receive(:generate)
 | |
|       allow(algolia_site).to receive(:keep_only_indexable_files)
 | |
|       allow(algolia_site).to receive(:init_rendering_progress_bar)
 | |
|       allow(algolia_site).to receive(:render)
 | |
|       allow(algolia_site).to receive(:push)
 | |
|       allow(algolia_site).to receive(:cleanup)
 | |
|       allow(algolia_site).to receive(:write)
 | |
|     end
 | |
| 
 | |
|     it 'should change the initial .write method' do
 | |
|       expect(overridden_method).to_not eq initial_method
 | |
|     end
 | |
| 
 | |
|     describe 'should call the preflight generation' do
 | |
|       before do
 | |
|         algolia_site.process
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(algolia_site).to have_received(:reset)
 | |
|         expect(algolia_site).to have_received(:read)
 | |
|         expect(algolia_site).to have_received(:generate)
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     describe 'should clean the list of files' do
 | |
|       before do
 | |
|         algolia_site.process
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(algolia_site).to have_received(:keep_only_indexable_files)
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     describe 'should set a progress bar' do
 | |
|       before do
 | |
|         algolia_site.process
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(algolia_site).to have_received(:init_rendering_progress_bar)
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     describe 'should convert markdown to html' do
 | |
|       before do
 | |
|         algolia_site.process
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(algolia_site).to have_received(:render)
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     describe 'should push records' do
 | |
|       before do
 | |
|         algolia_site.process
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(algolia_site).to have_received(:push)
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     describe 'should not call the original cleanup' do
 | |
|       before do
 | |
|         algolia_site.process
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(algolia_site).to_not have_received(:cleanup)
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     describe 'should not call the original write' do
 | |
|       before do
 | |
|         algolia_site.process
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(algolia_site).to_not have_received(:write)
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe 'Jekyll::Site#indexable_list' do
 | |
|     let(:algolia_site) { Jekyll::Algolia::Site.new(Jekyll.configuration) }
 | |
| 
 | |
|     subject { algolia_site.indexable_list(items) }
 | |
| 
 | |
|     describe 'remove non-indexable elements' do
 | |
|       let(:item1) { double('Item', name: 'foo', data: {}) }
 | |
|       let(:item2) { double('Item', name: 'bar', data: {}) }
 | |
|       let(:items) { [item1, item2] }
 | |
| 
 | |
|       before do
 | |
|         allow(file_browser).to receive(:indexable?).and_return(true)
 | |
|         allow(file_browser)
 | |
|           .to receive(:indexable?)
 | |
|           .with(item2)
 | |
|           .and_return(false)
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(subject.length).to eq 1
 | |
|         expect(subject[0]).to eq item1
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     describe 'set layout to nil' do
 | |
|       let(:items) do
 | |
|         [
 | |
|           double('Item', name: 'foo', data: {}),
 | |
|           double('Item', name: 'bar', data: { 'layout' => 'post' })
 | |
|         ]
 | |
|       end
 | |
| 
 | |
|       before do
 | |
|         allow(file_browser).to receive(:indexable?).and_return(true)
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(subject[0].data).to include('layout' => nil)
 | |
|         expect(subject[1].data).to include('layout' => nil)
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe 'Jekyll::Site#keep_only_indexable_files' do
 | |
|     let(:site) { Jekyll::Algolia::Site.new(Jekyll.configuration) }
 | |
|     let(:pages) { 'pages' }
 | |
|     let(:collections) { { foo: collection } }
 | |
|     let(:collection) { double('Collection', docs: 'collection') }
 | |
|     let(:static_files) { 'static_pages' }
 | |
| 
 | |
|     before do
 | |
|       allow(site)
 | |
|         .to receive(:indexable_list)
 | |
|       allow(collection).to receive(:docs=)
 | |
|       site.pages = pages
 | |
|       site.collections = collections
 | |
|       site.static_files = static_files
 | |
|     end
 | |
| 
 | |
|     describe 'should clean the pages' do
 | |
|       before do
 | |
|         expect(site)
 | |
|           .to receive(:indexable_list)
 | |
|           .with(pages)
 | |
|           .and_return('after_pages')
 | |
|         site.keep_only_indexable_files
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(site.pages).to eq 'after_pages'
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     describe 'should clean the documents' do
 | |
|       before do
 | |
|         allow(site)
 | |
|           .to receive(:indexable_list)
 | |
|           .with('collection')
 | |
|           .and_return('after_collection')
 | |
|         allow(collection)
 | |
|           .to receive(:docs=)
 | |
|           .with('after_collection')
 | |
|         site.keep_only_indexable_files
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(site).to have_received(:indexable_list).with('collection')
 | |
|         expect(collection).to have_received(:docs=).with('after_collection')
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     describe 'should clean the static files' do
 | |
|       before do
 | |
|         site.keep_only_indexable_files
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(site.static_files).to eq []
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe 'Jekyll::Site#indexable_item_count' do
 | |
|     let(:site) { Jekyll::Algolia::Site.new(Jekyll.configuration) }
 | |
|     let(:collections) do
 | |
|       {
 | |
|         foo: double('CollectionFoo', docs: docs_foo),
 | |
|         bar: double('CollectionBar', docs: docs_bar)
 | |
|       }
 | |
|     end
 | |
| 
 | |
|     subject { site.indexable_item_count }
 | |
| 
 | |
|     before do
 | |
|       site.pages = pages
 | |
|       site.collections = collections
 | |
|     end
 | |
| 
 | |
|     describe do
 | |
|       let(:pages) { %w[foo bar] }
 | |
|       let(:docs_foo) { [] }
 | |
|       let(:docs_bar) { [] }
 | |
|       it { should eq 2 }
 | |
|     end
 | |
|     describe do
 | |
|       let(:pages) { [] }
 | |
|       let(:docs_foo) { ['foo'] }
 | |
|       let(:docs_bar) { %w[bar baz] }
 | |
|       it { should eq 3 }
 | |
|     end
 | |
|     describe do
 | |
|       let(:pages) { [42] }
 | |
|       let(:docs_foo) { ['foo'] }
 | |
|       let(:docs_bar) { %w[bar baz] }
 | |
|       it { should eq 4 }
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe 'Jekyll::Site#init_rendering_progress_bar' do
 | |
|     let(:site) { Jekyll::Algolia::Site.new(Jekyll.configuration) }
 | |
|     let(:progress_bar_instance) { double('ProgressBarInstance') }
 | |
|     let(:item_count) { 2 }
 | |
| 
 | |
|     before do
 | |
|       allow(site).to receive(:indexable_item_count).and_return(item_count)
 | |
|       allow(progress_bar).to receive(:create).and_return(progress_bar_instance)
 | |
|       allow(Jekyll::Hooks).to receive(:register)
 | |
|       site.init_rendering_progress_bar
 | |
|     end
 | |
| 
 | |
|     it do
 | |
|       expect(progress_bar)
 | |
|         .to have_received(:create)
 | |
|         .with(
 | |
|           hash_including(total: item_count)
 | |
|         )
 | |
|       expect(Jekyll::Hooks)
 | |
|         .to have_received(:register)
 | |
|         .with(:pages, :post_render)
 | |
|       expect(Jekyll::Hooks)
 | |
|         .to have_received(:register)
 | |
|         .with(:documents, :post_render)
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe 'Jekyll::Site#push' do
 | |
|     let(:file_foo) { double('File', path: 'foo') }
 | |
|     let(:file_bar) { double('File', path: 'bar') }
 | |
|     let(:records_foo) { [{ name: 'foo1' }, { name: 'foo2' }] }
 | |
|     let(:records_bar) { [{ name: 'bar1' }, { name: 'bar2' }] }
 | |
|     let(:site) { Jekyll::Algolia::Site.new(Jekyll.configuration) }
 | |
|     let(:progress_bar_instance) { double('ProgressBarInstance') }
 | |
| 
 | |
|     before do
 | |
|       allow(site)
 | |
|         .to receive(:each_site_file)
 | |
|         .and_yield(file_foo)
 | |
|         .and_yield(file_bar)
 | |
|       allow(site).to receive(:indexable_item_count)
 | |
|       allow(progress_bar).to receive(:create).and_return(progress_bar_instance)
 | |
|       allow(progress_bar_instance).to receive(:increment)
 | |
|       allow(extractor).to receive(:run)
 | |
|       allow(extractor).to receive(:run).with(file_foo).and_return(records_foo)
 | |
|       allow(extractor).to receive(:run).with(file_bar).and_return(records_bar)
 | |
|       allow(extractor).to receive(:add_unique_object_id) { |arg| arg }
 | |
|       allow(file_browser).to receive(:indexable?).and_return(true)
 | |
|       allow(file_browser).to receive(:relative_path)
 | |
|       allow(hooks).to receive(:apply_all) { |arg| arg }
 | |
|       allow(logger).to receive(:verbose)
 | |
|       allow(indexer).to receive(:run)
 | |
|     end
 | |
| 
 | |
|     describe 'push records' do
 | |
|       before do
 | |
|         site.push
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(indexer)
 | |
|           .to have_received(:run)
 | |
|           .with([
 | |
|                   { name: 'foo1' },
 | |
|                   { name: 'foo2' },
 | |
|                   { name: 'bar1' },
 | |
|                   { name: 'bar2' }
 | |
|                 ])
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     describe 'exclude non-indexable elements' do
 | |
|       before do
 | |
|         expect(file_browser)
 | |
|           .to receive(:indexable?)
 | |
|           .with(file_bar)
 | |
|           .and_return(false)
 | |
| 
 | |
|         site.push
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(indexer)
 | |
|           .to have_received(:run)
 | |
|           .with(records_foo)
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     describe 'displaying number of files processed' do
 | |
|       before do
 | |
|         site.push
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(logger).to have_received(:verbose).with(/2 files/)
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     describe 'display path of files in verbose mode' do
 | |
|       before do
 | |
|         allow(file_browser)
 | |
|           .to receive(:relative_path)
 | |
|           .with('foo')
 | |
|           .and_return('foo-path')
 | |
|         allow(file_browser)
 | |
|           .to receive(:relative_path)
 | |
|           .with('bar')
 | |
|           .and_return('bar-path')
 | |
| 
 | |
|         site.push
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(logger).to have_received(:verbose).with(/foo-path/)
 | |
|         expect(logger).to have_received(:verbose).with(/bar-path/)
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     describe 'call hooks on all records' do
 | |
|       before do
 | |
|         site.push
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(hooks)
 | |
|           .to have_received(:apply_all)
 | |
|           .with([
 | |
|                   { name: 'foo1' },
 | |
|                   { name: 'foo2' },
 | |
|                   { name: 'bar1' },
 | |
|                   { name: 'bar2' }
 | |
|                 ],
 | |
|                 site)
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     describe 'add a unique id to each record' do
 | |
|       before do
 | |
|         site.push
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(extractor)
 | |
|           .to have_received(:add_unique_object_id)
 | |
|           .with(name: 'foo1')
 | |
|         expect(extractor)
 | |
|           .to have_received(:add_unique_object_id)
 | |
|           .with(name: 'foo2')
 | |
|         expect(extractor)
 | |
|           .to have_received(:add_unique_object_id)
 | |
|           .with(name: 'bar1')
 | |
|         expect(extractor)
 | |
|           .to have_received(:add_unique_object_id)
 | |
|           .with(name: 'bar2')
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     describe 'increment progress bar' do
 | |
|       before do
 | |
|         allow(site)
 | |
|           .to receive(:indexable_item_count)
 | |
|           .and_return(42)
 | |
| 
 | |
|         site.push
 | |
|       end
 | |
| 
 | |
|       it do
 | |
|         expect(progress_bar)
 | |
|           .to have_received(:create)
 | |
|           .with(hash_including(total: 42))
 | |
|         expect(progress_bar_instance).to have_received(:increment).twice
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe '.run' do
 | |
|     # Prevent the whole process to stop if Algolia config is not available
 | |
|     before do
 | |
|       allow(configurator)
 | |
|         .to receive(:assert_valid_credentials)
 | |
|         .and_return(true)
 | |
|     end
 | |
| 
 | |
|     let(:configuration) { Jekyll.configuration }
 | |
|     let(:algolia_site) { double('Jekyll::Algolia::Site', process: nil) }
 | |
|     before do
 | |
|       # Making sure all methods are called on the relevant objects
 | |
|       expect(Jekyll::Algolia::Site)
 | |
|         .to receive(:new)
 | |
|         .with(configuration)
 | |
|         .and_return(algolia_site)
 | |
|       expect(algolia_site)
 | |
|         .to receive(:process)
 | |
|     end
 | |
| 
 | |
|     it { current.init(configuration).run }
 | |
|   end
 | |
| end
 | |
| # rubocop:enable Metrics/BlockLength
 |