1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#!/usr/bin/env python
2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch# Copyright 2013 The Chromium Authors. All rights reserved.
3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch# Use of this source code is governed by a BSD-style license that can be
4ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch# found in the LICENSE file.
5ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
6ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochimport unittest
7ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
8558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochfrom file_system import FileNotFoundError
9ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochfrom link_error_detector import LinkErrorDetector
10ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochfrom servlet import Response
11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochfrom test_file_system import TestFileSystem
12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochfile_system = TestFileSystem({
14ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  'docs': {
15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    'templates': {
16ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      'public': {
17ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        'apps': {
18ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          '404.html': '404',
19ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          'index.html': '''
20ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            <h1 id="actual-top">Hello</h1>
21ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            <a href="#top">world</p>
22ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            <a href="#actual-top">!</a>
23ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            <a href="broken.json"></a>
24ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            <a href="crx.html"></a>
25ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            ''',
26ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          'crx.html': '''
27ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            <a href="index.html#actual-top">back</a>
28ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            <a href="broken.html"></a>
29ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            <a href="devtools.events.html">do to underscore translation</a>
30ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            ''',
31ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          'devtools_events.html': '''
32ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            <a href=" http://www.google.com/">leading space in href</a>
33ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            <a href=" index.html">home</a>
34ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            <a href="index.html#invalid"></a>
35ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            <a href="fake.html#invalid"></a>
36ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            ''',
37ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          'unreachable.html': '''
38ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            <p>so lonely</p>
39ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            <a href="#aoesu"></a>
40ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            <a href="invalid.html"></a>
41ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            ''',
42ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          'devtools_disconnected.html': ''
43ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        }
44ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      }
45ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    },
46ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    'static': {},
47ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    'examples': {},
48ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
49ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch})
50ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
51ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochclass LinkErrorDetectorTest(unittest.TestCase):
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  def _Render(self, path):
53ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    try:
54ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      return Response(
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          content=file_system.ReadSingle('docs/templates/public/' + path).Get(),
56ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          status=200)
57558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    except FileNotFoundError:
58ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      return Response(status=404)
59ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
60ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  def testGetBrokenLinks(self):
61ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    expected_broken_links = set([
62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      (404, 'apps/crx.html', 'apps/broken.html', 'target page not found'),
63a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      (404, 'apps/index.html', 'apps/broken.json', 'target page not found'),
64a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      (404, 'apps/unreachable.html', 'apps/invalid.html',
65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          'target page not found'),
66558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      (404, 'apps/devtools_events.html', 'apps/fake.html#invalid',
67558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch          'target page not found'),
68558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      (200, 'apps/devtools_events.html', 'apps/index.html#invalid',
69558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch          'target anchor not found'),
70558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      (200, 'apps/unreachable.html', '#aoesu', 'target anchor not found')])
71ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
72ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    link_error_detector = LinkErrorDetector(
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        file_system, self._Render, 'templates/public/', ('apps/index.html'))
74558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    broken_links = link_error_detector.GetBrokenLinks()
75ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
76ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    self.assertEqual(expected_broken_links, set(broken_links))
77ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
78ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  def testGetOrphanedPages(self):
79ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    expected_orphaned_pages = set([
80ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      'apps/unreachable.html',
81ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      'apps/devtools_disconnected.html'])
82ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
83ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    link_error_detector = LinkErrorDetector(
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        file_system, self._Render, 'templates/public/', ('apps/crx.html',))
85ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    orphaned_pages = link_error_detector.GetOrphanedPages()
86ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
87ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    self.assertEqual(expected_orphaned_pages, set(orphaned_pages))
88ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
89ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochif __name__ == '__main__':
90ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unittest.main()
91