<commit_before>require 'test_helper'
require 'gds_api/content_api'
require 'gds_api/test_helpers/content_api'

describe GdsApi::ContentApi do
  include GdsApi::TestHelpers::ContentApi

  before do
    @base_api_url = Plek.current.find("contentapi")
    @api = GdsApi::ContentApi.new(@base_api_url)
  end

  describe "sections" do
    it "should show a list of sections" do
      content_api_has_root_sections(["crime"])
      response = @api.sections

      # Old-style dictionary access
      first_section = response["results"][0]
      assert_equal "#{@base_api_url}/tags/crime.json", first_section["id"]

      # Also check attribute access
      first_section = response.first
      assert_equal "#{@base_api_url}/tags/crime.json", first_section.id
    end

    it "should allow iteration across pages" do
      first_page_url = "#{CONTENT_API_ENDPOINT}/tags.json?type=section"
      second_page_url = "#{CONTENT_API_ENDPOINT}/tags.json?type=section&page=2"

      first_page_body = plural_response_base.merge(
        "results" => ("a".."j").map { |letter| tag_for_slug("section-#{letter}", "section") }
      )
      stub_request(:get, first_page_url).to_return(
        status: 200,
        body: first_page_body.to_json,
        headers: {"Link" => "<#{second_page_url}>; rel=\"next\""}
      )
      second_page_body = plural_response_base.merge(
        "results" => ("k".."t").map { |letter| tag_for_slug("section-#{letter}", "section") }
      )
      stub_request(:get, second_page_url).to_return(
        status: 200,
        body: second_page_body.to_json,
        headers: {"Link" => "<#{first_page_url}>; rel=\"previous\""}
      )

      sections = @api.sections
      assert_equal 20, sections.with_subsequent_pages.count
      assert_equal "Section t", sections.with_subsequent_pages.to_a.last.title
    end

    it "should not load a page multiple times" do
      first_page_url = "#{CONTENT_API_ENDPOINT}/tags.json?type=section"
      second_page_url = "#{CONTENT_API_ENDPOINT}/tags.json?type=section&page=2"

      first_page_body = plural_response_base.merge(
        "results" => ("a".."j").map { |letter| tag_for_slug("section-#{letter}", "section") }
      )
      stub_request(:get, first_page_url).to_return(
        status: 200,
        body: first_page_body.to_json,
        headers: {"Link" => "<#{second_page_url}>; rel=\"next\""}
      )
      second_page_body = plural_response_base.merge(
        "results" => ("k".."t").map { |letter| tag_for_slug("section-#{letter}", "section") }
      )
      stub_request(:get, second_page_url).to_return(
        status: 200,
        body: second_page_body.to_json,
        headers: {"Link" => "<#{first_page_url}>; rel=\"previous\""}
      )

      sections = @api.sections

      3.times do
        # Loop through all the items, just to make sure we load all the pages
        sections.with_subsequent_pages.each do end
      end

      assert_requested :get, second_page_url, times: 1<commit_msg>Factor out section page stubbing, plus more tests.<commit_after>require 'test_helper'
require 'gds_api/content_api'
require 'gds_api/test_helpers/content_api'

describe GdsApi::ContentApi do
  include GdsApi::TestHelpers::ContentApi

  before do
    @base_api_url = Plek.current.find("contentapi")
    @api = GdsApi::ContentApi.new(@base_api_url)
  end

  describe "sections" do
    it "should show a list of sections" do
      content_api_has_root_sections(["crime"])
      response = @api.sections

      # Old-style dictionary access
      first_section = response["results"][0]
      assert_equal "#{@base_api_url}/tags/crime.json", first_section["id"]

      # Also check attribute access
      first_section = response.first
      assert_equal "#{@base_api_url}/tags/crime.json", first_section.id
    end

    def section_page_url(page_parameter)
      if page_parameter
        "#{CONTENT_API_ENDPOINT}/tags.json?type=section&page=#{page_parameter}"
      else
        "#{CONTENT_API_ENDPOINT}/tags.json?type=section"
      end
    end

    def stub_section_page(page_parameter, options)
      total_pages = options.fetch :of

      url = section_page_url(page_parameter)

      page_number = page_parameter || 1
      # e.g. page 2 -> 11..20
      range_start = (page_number - 1) * 10 + 1
      range_end = page_number * 10
      tags = (range_start..range_end).map { |number|
        tag_for_slug("section-#{number}", "section")
      }
      body = plural_response_base.merge(
        "results" => tags
      )

      links = []
      if page_number > 1
        links << "<#{section_page_url(page_number - 1)}>; rel=\"previous\""
      end
      if page_number < total_pages
        links << "<#{section_page_url(page_number + 1)}>; rel=\"next\""
      end

      stub_request(:get, url).to_return(
        status: 200,
        body: body.to_json,
        headers: {"Link" => links.join(",")}
      )
    end

    it "should allow iteration across pages" do
      [nil, 2].each do |page_parameter|
        stub_section_page(page_parameter, of: 2)
      end

      sections = @api.sections
      assert_equal 20, sections.with_subsequent_pages.count
      assert_equal "Section 20", sections.with_subsequent_pages.to_a.last.title
    end

    it "should iterate across three or more pages" do
      [nil, 2, 3].each do |page_parameter|
        stub_section_page(page_parameter, of: 3)
      end

      sections = @api.sections
      assert_equal 30, sections.with_subsequent_pages.count
      assert_equal "Section 30", sections.with_subsequent_pages.to_a.last.title
    end

    it "should not load a page multiple times" do
      [nil, 2].each do |page_parameter|
        stub_section_page(page_parameter, of: 2)
      end

      sections = @api.sections

      3.times do
        # Loop through all the items, just to make sure we load all the pages
        sections.with_subsequent_pages.each do end
      end

      assert_requested :get, section_page_url(2), times: 1
    end

    it "should display a single page of sections" do
      stub_section_page(nil, of: 1)
      sections = @api.sections
      assert_equal 10, sections.with_subsequent_pages.count
{'fraction_non_alphanumeric': 0.11958997722095673, 'fraction_numerical': 0.009599739668076798, 'mean_word_length': 3.0414201183431953, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7187661', 'n_tokens_mistral': 2039, 'n_tokens_neox': 1959, 'n_words': 418}