1#!/usr/bin/env python
2# Copyright (c) 2012 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6'''Unit tests for grit.tool.rc2grd'''
7
8import os
9import sys
10if __name__ == '__main__':
11  sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
12
13import re
14import StringIO
15import unittest
16
17from grit import grd_reader
18from grit.node import base
19from grit.tool import rc2grd
20
21
22class Rc2GrdUnittest(unittest.TestCase):
23  def testPlaceholderize(self):
24    tool = rc2grd.Rc2Grd()
25    original = "Hello %s, how are you? I'm $1 years old!"
26    msg = tool.Placeholderize(original)
27    self.failUnless(msg.GetPresentableContent() == "Hello TODO_0001, how are you? I'm TODO_0002 years old!")
28    self.failUnless(msg.GetRealContent() == original)
29
30  def testHtmlPlaceholderize(self):
31    tool = rc2grd.Rc2Grd()
32    original = "Hello <b>[USERNAME]</b>, how are you? I'm [AGE] years old!"
33    msg = tool.Placeholderize(original)
34    self.failUnless(msg.GetPresentableContent() ==
35                    "Hello BEGIN_BOLDX_USERNAME_XEND_BOLD, how are you? I'm X_AGE_X years old!")
36    self.failUnless(msg.GetRealContent() == original)
37
38  def testMenuWithoutWhitespaceRegression(self):
39    # There was a problem in the original regular expression for parsing out
40    # menu sections, that would parse the following block of text as a single
41    # menu instead of two.
42    two_menus = '''
43// Hyper context menus
44IDR_HYPERMENU_FOLDER MENU
45BEGIN
46    POPUP "HyperFolder"
47    BEGIN
48        MENUITEM "Open Containing Folder",      IDM_OPENFOLDER
49    END
50END
51
52IDR_HYPERMENU_FILE MENU
53BEGIN
54    POPUP "HyperFile"
55    BEGIN
56        MENUITEM "Open Folder",                 IDM_OPENFOLDER
57    END
58END
59
60'''
61    self.failUnless(len(rc2grd._MENU.findall(two_menus)) == 2)
62
63  def testRegressionScriptWithTranslateable(self):
64    tool = rc2grd.Rc2Grd()
65
66    # test rig
67    class DummyNode(base.Node):
68      def AddChild(self, item):
69        self.node = item
70      verbose = False
71      extra_verbose = False
72    tool.not_localizable_re = re.compile('')
73    tool.o = DummyNode()
74
75    rc_text = '''STRINGTABLE\nBEGIN\nID_BINGO "<SPAN id=hp style='BEHAVIOR: url(#default#homepage)'></SPAN><script>if (!hp.isHomePage('[$~HOMEPAGE~$]')) {document.write(""<a href=\\""[$~SETHOMEPAGEURL~$]\\"" >Set As Homepage</a> - "");}</script>"\nEND\n'''
76    tool.AddMessages(rc_text, tool.o)
77    self.failUnless(tool.o.node.GetCdata().find('Set As Homepage') != -1)
78
79    # TODO(joi) Improve the HTML parser to support translateables inside
80    # <script> blocks?
81    self.failUnless(tool.o.node.attrs['translateable'] == 'false')
82
83  def testRoleModel(self):
84    rc_text = ('STRINGTABLE\n'
85               'BEGIN\n'
86               '  // This should not show up\n'
87               '  IDS_BINGO "Hello %s, how are you?"\n'
88               '  // The first description\n'
89               '  IDS_BONGO "Hello %s, my name is %s, and yours?"\n'
90               '  IDS_PROGRAMS_SHUTDOWN_TEXT      "Google Desktop Search needs to close the following programs:\\n\\n$1\\nThe installation will not proceed if you choose to cancel."\n'
91               'END\n')
92    tool = rc2grd.Rc2Grd()
93    tool.role_model = grd_reader.Parse(StringIO.StringIO(
94      '''<?xml version="1.0" encoding="UTF-8"?>
95      <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
96        <release seq="3">
97          <messages>
98            <message name="IDS_BINGO">
99              Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you?
100            </message>
101            <message name="IDS_BONGO" desc="The other description">
102              Hello <ph name="USERNAME">%s<ex>Jakob</ex></ph>, my name is <ph name="ADMINNAME">%s<ex>Joi</ex></ph>, and yours?
103            </message>
104            <message name="IDS_PROGRAMS_SHUTDOWN_TEXT" desc="LIST_OF_PROGRAMS is replaced by a bulleted list of program names.">
105              Google Desktop Search needs to close the following programs:
106
107<ph name="LIST_OF_PROGRAMS">$1<ex>Program 1, Program 2</ex></ph>
108The installation will not proceed if you choose to cancel.
109            </message>
110          </messages>
111        </release>
112      </grit>'''), dir='.')
113
114    # test rig
115    class DummyOpts(object):
116      verbose = False
117      extra_verbose = False
118    tool.o = DummyOpts()
119    result = tool.Process(rc_text, '.\resource.rc')
120    self.failUnless(
121      result.children[2].children[2].children[0].attrs['desc'] == '')
122    self.failUnless(
123      result.children[2].children[2].children[0].children[0].attrs['name'] == 'USERNAME')
124    self.failUnless(
125      result.children[2].children[2].children[1].attrs['desc'] == 'The other description')
126    self.failUnless(
127      result.children[2].children[2].children[1].attrs['meaning'] == '')
128    self.failUnless(
129      result.children[2].children[2].children[1].children[0].attrs['name'] == 'USERNAME')
130    self.failUnless(
131      result.children[2].children[2].children[1].children[1].attrs['name'] == 'ADMINNAME')
132    self.failUnless(
133      result.children[2].children[2].children[2].children[0].attrs['name'] == 'LIST_OF_PROGRAMS')
134
135if __name__ == '__main__':
136  unittest.main()
137
138