Beispiel #1
0
def test_multiple_hooks():
    recorded_tasks = {}
    counter = 0

    def record_page(task_info):
        recorded_tasks[task_info.get_a_url()] = task_info

    def increment_counter(task_info):
        nonlocal counter
        counter += 1

    with context_for_test('app_2pages') as module:
        config = {
            'output': {
                'type': 'dict'
            },
            'prefix': 'http://example.com/',
            'hooks': {
                'page_frozen': [record_page, increment_counter]
            },
        }

        freeze(module.app, config)

    print(recorded_tasks)

    assert len(recorded_tasks) == 2
    assert counter == 2

    info = recorded_tasks['http://example.com:80/']
    assert info.path == 'index.html'

    info = recorded_tasks['http://example.com:80/second_page.html']
    assert info.path == 'second_page.html'
Beispiel #2
0
def test_taskinfo_has_freezeinfo():
    freezeinfos = []

    def start_hook(freezeinfo):
        freezeinfos.append(freezeinfo)

    def page_frozen_hook(pageinfo):
        freezeinfos.append(pageinfo.freeze_info)

    with context_for_test('app_simple') as module:
        config = {
            'output': {
                'type': 'dict'
            },
            'prefix': 'http://example.com/',
            'hooks': {
                'start': [start_hook],
                'page_frozen': [page_frozen_hook],
            },
        }

        freeze(module.app, config)

    a, b = freezeinfos
    assert a is b
Beispiel #3
0
def test_add_hook():
    recorded_tasks = {}

    def register_hook(freeze_info):
        freeze_info.add_hook('page_frozen', record_page)

    def record_page(task_info):
        recorded_tasks[task_info.get_a_url()] = task_info

    with context_for_test('app_2pages') as module:
        config = {
            'output': {
                'type': 'dict'
            },
            'prefix': 'http://example.com/',
            'hooks': {
                'start': [register_hook]
            },
        }

        freeze(module.app, config)

    print(recorded_tasks)

    assert len(recorded_tasks) == 2

    info = recorded_tasks['http://example.com:80/']
    assert info.path == 'index.html'

    info = recorded_tasks['http://example.com:80/second_page.html']
    assert info.path == 'second_page.html'
Beispiel #4
0
def test_task_counts_extra_page():
    recorded_done_counts = []
    recorded_paths = set()
    expected_total = 3

    def record_start(freeze_info):
        check_task_counts(freeze_info, expected_total)
        assert freeze_info.done_task_count == 0

    def record_page(task_info):
        check_task_counts(task_info.freeze_info, expected_total)
        recorded_done_counts.append(task_info.freeze_info.done_task_count)
        recorded_paths.add(task_info.path)

    with context_for_test('app_with_extra_page_deep') as module:
        config = {
            **module.freeze_config,
            'output': {
                'type': 'dict'
            },
            'prefix': 'http://example.com/',
            'hooks': {
                'start': [record_start],
                'page_frozen': [record_page],
            },
        }

        freeze(module.app, config)

    assert recorded_done_counts == [1, 2, 3]
    assert recorded_paths == {
        'index.html',
        'extra/index.html',
        'extra/extra_deep/index.html',
    }
Beispiel #5
0
def test_modified_mime_db_file(tmp_path):
    """Integration test with modified mime-db, where is purposely
    set wrong extensions for MIME image/png to check if our db was used.

    """
    MIME_DB_TO_JSON = {
        "image/png": {
            "source": "iana",
            "compressible": False,
            "extensions": ["Jpeg","jPg"]
        },
        'text/html': {
            "extensions": ["htmL"]
        }
    }
    builddir = tmp_path / 'build'
    db_path = tmp_path / "mime_db.json"

    with open(db_path, mode="w") as mime_db:
        json.dump(MIME_DB_TO_JSON, mime_db)

    with context_for_test('app_wrong_mimetype') as module:
        freeze_config = {
            'output': str(builddir),
            'mime_db_file': str(db_path)
        }

        freeze(module.app, freeze_config)

    assert (builddir / 'index.html').exists()
    # 'image.jpg' exists because we linked jpg extension with MIME 'image/png'
    assert (builddir / 'image.jpg').exists()
Beispiel #6
0
def test_one_page(tmp_path):
    freeze(app, tmp_path)

    with open(tmp_path / "index.html", encoding='utf-8') as f:
        read_text = f.read()

    assert read_text == """
Beispiel #7
0
def test_tasks_are_limited(tmp_path):
    NUM_PAGES = MAX_RUNNING_TASKS * 2
    currently_processed_pages = 0

    class ResultIterator:
        def __init__(self):
            self.contents = iter([b'a', b'b'])

        def __iter__(self):
            return self

        def __next__(self):
            assert currently_processed_pages <= MAX_RUNNING_TASKS
            result = next(self.contents)
            return result

        def close(self):
            nonlocal currently_processed_pages
            currently_processed_pages -= 1

    def app(environ, start_response):
        nonlocal currently_processed_pages
        currently_processed_pages += 1
        start_response('200 OK', [('Content-type', 'text/html')])
        return ResultIterator()

    config = {
        'output': str(tmp_path),
        'extra_pages': [f'{n}.html' for n in range(NUM_PAGES)],
    }

    freeze(app, config)
Beispiel #8
0
def test_output_dict(tmp_path, monkeypatch, app_name):
    app_path = FIXTURES_PATH / app_name
    error_path = app_path / 'error.txt'

    # Add FIXTURES_PATH to sys.path, the list of directories that `import`
    # looks in
    monkeypatch.syspath_prepend(str(app_path))
    sys.modules.pop('app', None)
    try:
        module = importlib.import_module('app')
        app = module.app

        freeze_config = getattr(module, 'freeze_config', {})
        freeze_config['output'] = 'dict'

        if error_path.exists():
            with pytest.raises(ValueError):
                freeze(app, freeze_config)
        else:
            result = freeze(app, freeze_config)
            expected_dict = getattr(module, 'expected_dict', None)

            if expected_dict is None:
                pytest.skip('No expected_dict')

            assert result == expected_dict

    finally:
        sys.modules.pop('app', None)
Beispiel #9
0
def test_freezeinfo_add_404_url(reason, expected_reasons):
    hook_called = False

    def start_hook(freezeinfo):
        nonlocal hook_called
        hook_called = True

        freezeinfo.add_url(
            'http://example.com/404-page.html',
            reason=reason,
        )

    with context_for_test('app_with_extra_page') as module:
        config = {
            'output': {
                'type': 'dict'
            },
            'prefix': 'http://example.com/',
            'hooks': {
                'start': [start_hook]
            },
        }

        with raises_multierror_with_one_exception(UnexpectedStatus) as e:
            freeze(module.app, config)
        assert e.freezeyt_task.reasons == expected_reasons
Beispiel #10
0
def test_overwrite_dir_with_index(tmp_path):
    builddir = tmp_path / 'build'
    builddir.mkdir()
    index_path = builddir / 'index.html'
    index_path.write_text('<html></html>')

    old_path = builddir / 'old.dat'
    old_path.write_text('1234')

    old_dir_path = builddir / 'dir'
    old_dir_path.mkdir()

    config = {
        **freeze_config,
        'output': {
            'type': 'dir',
            'dir': builddir
        },
    }

    freeze(app, config)
    assert index_path.exists()

    assert not old_path.exists()
    assert not old_dir_path.exists()
Beispiel #11
0
def test_let_incomplete_dir_intact(tmp_path):
    output_dir = tmp_path / "output"
    config = {"cleanup": False, "output": str(output_dir)}
    with raises_multierror_with_one_exception(UnexpectedStatus):
        freeze(app, config)
    assert output_dir.exists()  # the output dir has to exist
    assert (output_dir / "index.html"
            ).exists()  # the index.html file inside output dir has to exist
Beispiel #12
0
def test_cleanup_empty_app(tmp_path):
    """Test that cleanup succeeds even when no page is frozen"""

    output_dir = tmp_path / "output2"
    config = {"cleanup": True, "output": str(output_dir)}
    with raises_multierror_with_one_exception(UnexpectedStatus):
        freeze(empty_app, config)
    assert not output_dir.exists()  # the output dir has to be gone
Beispiel #13
0
def test_circular_redirect(tmp_path, monkeypatch):
    with context_for_test('circular_redirect') as module:
        freeze_config = module.freeze_config

        freeze_config['output'] = {'type': 'dir', 'dir': tmp_path}
        freeze_config['status_handlers'] = {'3xx': 'follow'}

        with pytest.raises(InfiniteRedirection):
            freeze(module.app, freeze_config)
Beispiel #14
0
def test_simple_output_specification(tmp_path):
    expected = FIXTURES_PATH / 'app_2pages' / 'test_expected_output'

    with context_for_test('app_2pages') as module:
        freeze_config = {'output': str(tmp_path)}

        freeze(module.app, freeze_config)

        assert_dirs_same(tmp_path, expected)
Beispiel #15
0
def test_output(tmp_path, monkeypatch, app_name):
    app_path = FIXTURES_PATH / app_name
    error_path = app_path / 'error.txt'

    with context_for_test(app_name) as module:
        module = importlib.import_module('app')
        app = module.app

        freeze_config = getattr(module, 'freeze_config', {})
        expected_dict = getattr(module, 'expected_dict', None)
        expecting_dir = not getattr(module, 'no_expected_directory', False)

        freeze_config['output'] = {'type': 'dir', 'dir': tmp_path}

        if error_path.exists():
            with pytest.raises(ValueError) as exc:
                freeze(app, freeze_config)
            exception_name = exc.type.__name__
            expected_name = error_path.read_text().strip()
            assert exception_name == expected_name
        else:
            # Non error app.

            # We want to check against expected data stored in a directory
            # and/or in a dict. At least one of those must exist.
            if not expecting_dir and expected_dict is None:
                raise AssertionError(f'({app_name}) is not contain any' +
                                     'expected output (dict or dir)')

            if expecting_dir:
                # test the output saved in dir 'test_expected_output'
                freeze(app, freeze_config)  # freeze content to tmp_path
                expected = app_path / 'test_expected_output'

                if not expected.exists():
                    make_output = os.environ.get('TEST_CREATE_EXPECTED_OUTPUT')
                    if make_output == '1':
                        shutil.copytree(tmp_path, expected)
                    else:
                        raise AssertionError(
                            f'Expected output directory ({expected}) does not exist. '
                            +
                            'Run with TEST_CREATE_EXPECTED_OUTPUT=1 to create it'
                        )

                assert_dirs_same(tmp_path, expected)

            if expected_dict is not None:
                # test the output saved in dictionary
                freeze_config['output'] = {'type': 'dict'}

                result = freeze(app, freeze_config)  # freeze content to dict

                assert result == expected_dict
Beispiel #16
0
def test_external_extra_files(tmp_path):
    with context_for_test('app_2pages') as module:
        freeze_config = {
            'output': {
                'type': 'dict'
            },
            'extra_pages': ['http://external.example/foo.html'],
        }

        with pytest.raises(ExternalURLError):
            freeze(module.app, freeze_config)
Beispiel #17
0
def test_except_star():
    with context_for_test('app_various_errors') as module:
        app = module.app
        config = {
            'output': {'type': 'dict'},
        }

        try:
            freeze(app, config)
        except* TypeError as type_errors:
            assert len(type_errors.exceptions) == 2
        except* UnexpectedStatus as status_errors:
            assert len(status_errors.exceptions) == 1
Beispiel #18
0
def test_do_not_cleanup_if_directory_exists_error(tmp_path):
    output_dir = tmp_path / "output4"
    output_dir.mkdir()
    file_path = output_dir / 'important.dat'
    file_path.write_text('inportant text')

    config = {"cleanup": True, "output": str(output_dir)}

    with pytest.raises(DirectoryExistsError):
        freeze(app, config)

    assert output_dir.exists()  # the output dir has to exist
    assert (output_dir / 'important.dat'
            ).exists()  # the important.dat file inside output dir has to exist
Beispiel #19
0
def test_multierror(tmp_path, monkeypatch):
    with context_for_test('app_2_broken_links') as module:
        freeze_config = {
            'output': {'type': 'dir', 'dir': tmp_path},
        }

        with pytest.raises(MultiError) as excinfo:
            freeze(module.app, freeze_config)

        multierror = excinfo.value
        assert len(multierror.exceptions) == 2
        for exception in multierror.exceptions:
            with pytest.raises(UnexpectedStatus):
                raise exception
Beispiel #20
0
def test_reason_homepage():
    app = Flask(__name__)
    config = {
        'prefix': 'http://localhost/',
        'output': {
            'type': 'dict'
        },
    }

    with raises_multierror_with_one_exception(UnexpectedStatus) as e:
        freeze(app, config)
    assert str(e.value.url) == 'http://localhost:80/'
    assert e.value.status[:3] == '404'
    assert e.freezeyt_task.reasons == ['site root (homepage)']
Beispiel #21
0
def test_overwrite_empty_dir(tmp_path):
    builddir = tmp_path / 'build'
    builddir.mkdir()
    index_path = builddir / 'index.html'

    config = {
        **freeze_config,
        'output': {
            'type': 'dir',
            'dir': builddir
        },
    }

    freeze(app, config)
    assert index_path.exists()
Beispiel #22
0
def test_page_frozen_hook_by_name():
    with context_for_test('app_2pages') as module:
        config = {
            'output': {
                'type': 'dict'
            },
            'prefix': 'http://example.com/',
            'hooks': {
                'page_frozen': [f'{__name__}:hook']
            },
        }

        _recorded_hook_calls.clear()
        freeze(module.app, config)
        assert len(_recorded_hook_calls) == 2
Beispiel #23
0
def test_succesfully_loaded_get_mimetype_config(tmp_path, get_mimetypeID):
    """Test if user configuration of external functions get_mimetype
    is loaded and used during web app freezing.
    """
    builddir = tmp_path / 'build'

    with context_for_test('default_mimetype_plain') as module:
        freeze_config = {
            'output': str(builddir),
            'get_mimetype': GET_MIMETYPES[get_mimetypeID],
        }

        freeze(module.app, freeze_config)

        assert (builddir / 'index.html').exists()
        assert (builddir / 'textfile').exists()
Beispiel #24
0
def test_get_no_links(tmp_path):
    """Test configuration of no url_finders.
    We should get just root page.
    """
    builddir = tmp_path / 'build'

    with context_for_test('app_2pages') as module:
        freeze_config = {
            'output': str(builddir),
            'url_finders': {},
        }

        freeze(module.app, freeze_config)

    assert (builddir / 'index.html').exists()
    assert not (builddir / 'second_page.html').exists()
Beispiel #25
0
def test_close():
    closed = False

    class SpecialResult:
        def __init__(self):
            self.values = [b'body', b' ', b'content']
            self.position = 0

        def __next__(self):
            if self.position < len(self.values):
                value = self.values[self.position]
                self.position += 1
                return value
            else:
                raise StopIteration()

        def __iter__(self):
            return self

        def close(self):
            nonlocal closed
            closed = True

    def simple_app(environ, start_response):
        # regular application code here
        status = "200 OK"
        response_headers = [("content-type", "text/html")]
        start_response(status, response_headers)
        return SpecialResult()

    config = {'output': {'type': 'dict'}}
    expected = {'index.html': b'body content'}

    assert freeze(simple_app, config) == expected
    assert closed == True
Beispiel #26
0
def test_do_not_overwrite_existing_dir(tmp_path):
    builddir = tmp_path / 'build'
    builddir.mkdir()
    file_path = builddir / 'important.dat'
    file_path.write_text('1234')

    config = {
        **freeze_config,
        'output': {
            'type': 'dir',
            'dir': builddir
        },
    }

    with pytest.raises(DirectoryExistsError):
        freeze(app, config)
Beispiel #27
0
def test_page_frozen_hook_with_redirects(policy):
    recorded_tasks = []

    def record_page(task_info):
        recorded_tasks.append(task_info.path)

    with context_for_test('app_redirects') as module:
        config = dict(module.freeze_config)
        config['output'] = {'type': 'dict'}
        config['hooks'] = {'page_frozen': [record_page]}
        config['redirect_policy'] = policy
        output = freeze(module.app, config)

    output_paths = []

    def add_output_to_output_paths(dict_to_add, path_so_far):
        for key, value in dict_to_add.items():
            if isinstance(value, bytes):
                output_paths.append(path_so_far + key)
            else:
                add_output_to_output_paths(value, path_so_far + key + '/')

    add_output_to_output_paths(output, '')

    recorded_tasks.sort()
    output_paths.sort()

    assert recorded_tasks == output_paths
Beispiel #28
0
def test_default_handlers(response_status):
    app = Flask(__name__)
    config = {
        'output': {
            'type': 'dict'
        },
    }

    @app.route('/')
    def index():
        return Response(response='Hello world!', status=response_status)

    with pytest.raises(UnexpectedStatus) as e:
        freeze(app, config)

    assert e.value.status[:3] == f'{response_status}'
Beispiel #29
0
def test_func_to_files(tmp_path):
    builddir = tmp_path / 'build'

    config = {
        **freeze_config,
        'output': {'type': 'dir', 'dir': builddir},
    }

    freeze(app, config)

    assert (builddir / 'index.html').exists()
    assert (builddir / '.nojekyll').exists()
    assert (builddir / 'CNAME').exists()
    assert (builddir / 'smile.png').exists()
    assert (builddir / 'bin_range.dat').exists()
    assert (builddir / 'smile2.png').exists()
Beispiel #30
0
def test_page_failed_hook():
    records = []
    expected_total = 3

    def record_frozen(task_info):
        check_task_counts(task_info.freeze_info, expected_total)
        records.append((
            'frozen',
            task_info.path,
            task_info.freeze_info.total_task_count,
            task_info.freeze_info.done_task_count,
            task_info.freeze_info.failed_task_count,
        ))
        assert task_info.exception == None

    def record_fail(task_info):
        check_task_counts(task_info.freeze_info, expected_total)
        records.append((
            'failed',
            task_info.path,
            task_info.freeze_info.total_task_count,
            task_info.freeze_info.done_task_count,
            task_info.freeze_info.failed_task_count,
        ))
        assert isinstance(task_info.exception, UnexpectedStatus)

    with context_for_test('app_2_broken_links') as module:
        config = {
            'output': {
                'type': 'dict'
            },
            'prefix': 'http://example.com/',
            'hooks': {
                'page_frozen': [record_frozen],
                'page_failed': [record_fail],
            },
        }

        with pytest.raises(MultiError):
            freeze(module.app, config)

    assert records == [
        ('frozen', 'index.html', 3, 1, 0),
        ('failed', 'nowhere', 3, 2, 1),
        ('failed', 'also_nowhere', 3, 3, 2),
    ]