<commit_before>ENV["RAILS_ENV"] = "test"
require File.expand_path('../../../config/environment', __FILE__)

FLOW_REGISTRY_OPTIONS[:preload_flows] = false

require 'rails/test_help'

require 'webmock'
WebMock.disable_net_connect!(allow_localhost: true)

require_relative '../support/fixture_methods'
require_relative '../support/world_location_stubbing_methods'

require 'gds_api/test_helpers/content_api'
require 'gds_api/test_helpers/imminence'

require 'mocha/api'

class SmartAnswersRegressionTest < ActionController::TestCase
  i_suck_and_my_tests_are_order_dependent!
  RUN_ME_LAST = 'zzzzzzzzzzz run me last'

  class << self
    def setup_has_run!
      @setup_has_run = true
    end

    def setup_has_run?
      @setup_has_run
    end

    def webmock_teardown_hook_installed?
      Minitest::Test.method_defined?(:teardown_with_webmock)
    end

    def custom_teardown_hook_installed?
      Minitest::Test.method_defined?(:teardown_with_customisations)
    end

    def teardown_hooks_installed?
      webmock_teardown_hook_installed? || custom_teardown_hook_installed?
    end
  end

  include GdsApi::TestHelpers::ContentApi
  include GdsApi::TestHelpers::Imminence
  include WebMock::API
  include FixtureMethods
  include Mocha::API
  include WorldLocationStubbingMethods

  tests SmartAnswersController

  SmartAnswerTestHelper.responses_and_expected_results.each do |file|
    filename  = File.basename(file, '.yml')
    flow_name = filename[/(.*)-responses-and-expected-results/, 1]

    smart_answer_helper = SmartAnswerTestHelper.new(flow_name)

    next unless smart_answer_helper.run_regression_tests?

    smart_answer_helper.delete_saved_output_files
    responses_and_expected_results = smart_answer_helper.read_responses_and_expected_results

    context "Smart Answer: #{flow_name}" do
      setup do
        Timecop.freeze(smart_answer_helper.current_time)

        next if self.class.setup_has_run? && !self.class.teardown_hooks_installed?
        stub_content_api_default_artefact
        WebMock.stub_request(:get, WorkingDays::BANK_HOLIDAYS_URL).to_return(body: File.open(fixture_file('bank_holidays.json')))

        setup_worldwide_locations

        imminence_has_areas_for_postcode("PA3%202SW",  [{ slug: 'renfrewshire-council', country_name: 'Scotland' }])
        imminence_has_areas_for_postcode("B1%201PW",   [{ slug: "birmingham-city-council", country_name: 'England' }])
        imminence_has_areas_for_postcode("WC2B%206SE", [{ slug: 'london', country_name: 'England' }])

        self.class.setup_has_run!
      end

      should "have up to date checksum data" do
        message = []
        message << "Expected #{smart_answer_helper.files_checksum_path} to exist and to contain up to date data"
        message << "Use the generate-checksums-for-smart-answer script to update it"
        assert_equal false, smart_answer_helper.files_checksum_data_needs_updating?, message.join('. ')
      end

      should "ensure all nodes are being exercised" do
        flow = SmartAnswer::FlowRegistry.instance.find(flow_name)

        nodes_exercised_in_test = responses_and_expected_results.inject([]) do |array, hash|
          current_node = hash[:current_node]
          next_node    = hash[:next_node]
          array << current_node unless array.include?(current_node)
          array << next_node unless array.include?(next_node)
          array
        end

        unexercised_nodes = flow.nodes.map(&:name).map(&:to_sym) - nodes_exercised_in_test
        assert_equal true, unexercised_nodes.empty?, "Not all nodes are being exercised: #{unexercised_nodes.sort}"
      end

      should "render and save the landing page" do
        get :show, id: flow_name, format: 'txt'
        assert_response :success

        artefact_path = smart_answer_helper.save_output([flow_name], response)
        assert_no_output_diff artefact_path if ENV['ASSERT_EACH_ARTEFACT'].present?
      end

      should "render and save the first question page" do
        get :show, id: flow_name, started: 'y', format: 'html'
        assert_response :success

        artefact_path = smart_answer_helper.save_output(['y'], response, extension: 'html')
        assert_no_output_diff artefact_path if ENV['ASSERT_EACH_ARTEFACT'].present?
      end

      visited_nodes = Set.new
      responses_and_expected_results.each do |responses_and_expected_node|
        next_node     = responses_and_expected_node[:next_node]
        responses     = responses_and_expected_node[:responses]
        question_node = !responses_and_expected_node[:outcome_node]

        next if question_node && visited_nodes.include?(next_node)
        visited_nodes << next_node

        should "render and save output for responses: #{responses.join(', ')}" do
          format = question_node ? 'html' : 'txt'
          get :show, id: flow_name, started: 'y', responses: responses.join('/'), format: format
          assert_response :success
<commit_msg>Render regression test artefacts for question pages as text<commit_after>ENV["RAILS_ENV"] = "test"
require File.expand_path('../../../config/environment', __FILE__)

FLOW_REGISTRY_OPTIONS[:preload_flows] = false

require 'rails/test_help'

require 'webmock'
WebMock.disable_net_connect!(allow_localhost: true)

require_relative '../support/fixture_methods'
require_relative '../support/world_location_stubbing_methods'

require 'gds_api/test_helpers/content_api'
require 'gds_api/test_helpers/imminence'

require 'mocha/api'

class SmartAnswersRegressionTest < ActionController::TestCase
  i_suck_and_my_tests_are_order_dependent!
  RUN_ME_LAST = 'zzzzzzzzzzz run me last'

  class << self
    def setup_has_run!
      @setup_has_run = true
    end

    def setup_has_run?
      @setup_has_run
    end

    def webmock_teardown_hook_installed?
      Minitest::Test.method_defined?(:teardown_with_webmock)
    end

    def custom_teardown_hook_installed?
      Minitest::Test.method_defined?(:teardown_with_customisations)
    end

    def teardown_hooks_installed?
      webmock_teardown_hook_installed? || custom_teardown_hook_installed?
    end
  end

  include GdsApi::TestHelpers::ContentApi
  include GdsApi::TestHelpers::Imminence
  include WebMock::API
  include FixtureMethods
  include Mocha::API
  include WorldLocationStubbingMethods

  tests SmartAnswersController

  SmartAnswerTestHelper.responses_and_expected_results.each do |file|
    filename  = File.basename(file, '.yml')
    flow_name = filename[/(.*)-responses-and-expected-results/, 1]

    smart_answer_helper = SmartAnswerTestHelper.new(flow_name)

    next unless smart_answer_helper.run_regression_tests?

    smart_answer_helper.delete_saved_output_files
    responses_and_expected_results = smart_answer_helper.read_responses_and_expected_results

    context "Smart Answer: #{flow_name}" do
      setup do
        Timecop.freeze(smart_answer_helper.current_time)

        next if self.class.setup_has_run? && !self.class.teardown_hooks_installed?
        stub_content_api_default_artefact
        WebMock.stub_request(:get, WorkingDays::BANK_HOLIDAYS_URL).to_return(body: File.open(fixture_file('bank_holidays.json')))

        setup_worldwide_locations

        imminence_has_areas_for_postcode("PA3%202SW",  [{ slug: 'renfrewshire-council', country_name: 'Scotland' }])
        imminence_has_areas_for_postcode("B1%201PW",   [{ slug: "birmingham-city-council", country_name: 'England' }])
        imminence_has_areas_for_postcode("WC2B%206SE", [{ slug: 'london', country_name: 'England' }])

        self.class.setup_has_run!
      end

      should "have up to date checksum data" do
        message = []
        message << "Expected #{smart_answer_helper.files_checksum_path} to exist and to contain up to date data"
        message << "Use the generate-checksums-for-smart-answer script to update it"
        assert_equal false, smart_answer_helper.files_checksum_data_needs_updating?, message.join('. ')
      end

      should "ensure all nodes are being exercised" do
        flow = SmartAnswer::FlowRegistry.instance.find(flow_name)

        nodes_exercised_in_test = responses_and_expected_results.inject([]) do |array, hash|
          current_node = hash[:current_node]
          next_node    = hash[:next_node]
          array << current_node unless array.include?(current_node)
          array << next_node unless array.include?(next_node)
          array
        end

        unexercised_nodes = flow.nodes.map(&:name).map(&:to_sym) - nodes_exercised_in_test
        assert_equal true, unexercised_nodes.empty?, "Not all nodes are being exercised: #{unexercised_nodes.sort}"
      end

      should "render and save the landing page" do
        get :show, id: flow_name, format: 'txt'
        assert_response :success

        artefact_path = smart_answer_helper.save_output([flow_name], response)
        assert_no_output_diff artefact_path if ENV['ASSERT_EACH_ARTEFACT'].present?
      end

      should "render and save the first question page" do
        get :show, id: flow_name, started: 'y', format: 'txt'
        assert_response :success

        artefact_path = smart_answer_helper.save_output(['y'], response, extension: 'txt')
        assert_no_output_diff artefact_path if ENV['ASSERT_EACH_ARTEFACT'].present?
      end

      visited_nodes = Set.new
      responses_and_expected_results.each do |responses_and_expected_node|
        next_node     = responses_and_expected_node[:next_node]
        responses     = responses_and_expected_node[:responses]
        question_node = !responses_and_expected_node[:outcome_node]

        next if question_node && visited_nodes.include?(next_node)
        visited_nodes << next_node

        should "render and save output for responses: #{responses.join(', ')}" do
          format = 'txt'
          get :show, id: flow_name, started: 'y', responses: responses.join('/'), format: format
          assert_response :success

{'fraction_non_alphanumeric': 0.09069837750680237, 'fraction_numerical': 0.002620175350196513, 'mean_word_length': 3.934858279462954, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, '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': '4885255', 'n_tokens_mistral': 3184, 'n_tokens_neox': 3093, 'n_words': 594}