Version 1.0.0
@@ -0,0 +1,72 @@ | ||
1 | + | |
2 | +require 'redmine' | |
3 | +require_dependency 'testlinklink_asset_tag_helper_patch' | |
4 | +require_dependency 'testlinklink_view_layouts_base_html_head_hook' | |
5 | + | |
6 | +Redmine::Plugin.register :redmine_testlinklink do | |
7 | + name 'Testlink Link plugin' | |
8 | + author 'M. Yoshida' | |
9 | + description 'Links the test case, the project and so on from Redmine to TestLink.' | |
10 | + version '1.0.0' | |
11 | + url 'http://www.r-labs.org/projects/rp-testlinklink/wiki/TestLinkLinkEn' | |
12 | + author_url 'http://yohshiy.blog.fc2.com/' | |
13 | + requires_redmine :version_or_higher => '2' | |
14 | + | |
15 | + settings :default => { | |
16 | + 'testlink_address' => 'http://localhost/testlink', | |
17 | + 'testlink_version' => '1.8', | |
18 | + 'default_report_toc' => false, | |
19 | + 'default_report_header' => false, | |
20 | + 'default_report_summary' => 1, | |
21 | + 'default_report_body' => false, | |
22 | + 'default_report_author' => false, | |
23 | + 'default_report_keyword' => false, | |
24 | + 'default_report_cfields' => false, | |
25 | + 'default_report_passfail' => 1, | |
26 | + 'default_report_metrics' => false, | |
27 | + 'default_planreport_toc' => false, | |
28 | + 'default_planreport_header' => false, | |
29 | + 'default_planreport_summary' => 1, | |
30 | + 'default_planreport_body' => false, | |
31 | + 'default_planreport_author' => false, | |
32 | + 'default_planreport_keyword' => false, | |
33 | + 'default_planreport_cfields' => false, | |
34 | + 'default_planreport_testplan' => false | |
35 | + }, :partial => 'settings/testlinklink_settings' | |
36 | +end | |
37 | + | |
38 | + | |
39 | +Redmine::WikiFormatting::Macros.register do | |
40 | + desc "TestLink link macro" | |
41 | + macro :testlink do |obj, args| | |
42 | + tl = TestLinkLink.new(*args) | |
43 | + tl.link | |
44 | + end | |
45 | +end | |
46 | + | |
47 | +Redmine::WikiFormatting::Macros.register do | |
48 | + desc "TestLink TestCase link macro" | |
49 | + macro :testcase do |obj, args| | |
50 | + tl = TestLinkLink.new('case', *args) | |
51 | + tl.link | |
52 | + end | |
53 | +end | |
54 | + | |
55 | +Redmine::WikiFormatting::Macros.register do | |
56 | + desc "TestLink TestReport link macro" | |
57 | + macro :testreport do |obj, args| | |
58 | + tl = TestLinkLink.new('report', *args) | |
59 | + tl.link | |
60 | + end | |
61 | +end | |
62 | + | |
63 | + | |
64 | +Redmine::WikiFormatting::Macros.register do | |
65 | + desc "TestLink TestFile link macro" | |
66 | + macro :testfile do |obj, args| | |
67 | + fmtname = args.shift | |
68 | + tl = TestLinkLink.new(*args) | |
69 | + tl.formatname = fmtname | |
70 | + tl.link | |
71 | + end | |
72 | +end |
@@ -0,0 +1,33 @@ | ||
1 | +require_dependency "redmine/wiki_formatting/textile/helper" | |
2 | + | |
3 | +module Redmine | |
4 | + module WikiFormatting | |
5 | + module Textile | |
6 | + module Helper | |
7 | + | |
8 | + def heads_for_wiki_formatter_with_testlinklink | |
9 | + heads_for_wiki_formatter_without_testlinklink | |
10 | + unless @heads_for_wiki_formatter_testlinklink_included | |
11 | + content_for :header_tags do | |
12 | + out = stylesheet_link_tag("testcase.css", :plugin => "redmine_testlinklink") | |
13 | + out += javascript_tag <<-javascript_tag | |
14 | + jsToolBar.prototype.elements.testcase = { | |
15 | + type: 'button', | |
16 | + title: '#{l(:label_tag_testcase)}', | |
17 | + fn: { | |
18 | + wiki: function() { this.encloseSelection("{{testcase(", ")}}") } | |
19 | + } | |
20 | + } | |
21 | + javascript_tag | |
22 | + out | |
23 | + end | |
24 | + @heads_for_wiki_formatter_testlinklink_included = true | |
25 | + end | |
26 | + end | |
27 | + | |
28 | + alias_method_chain :heads_for_wiki_formatter, :testlinklink | |
29 | + | |
30 | + end | |
31 | + end | |
32 | + end | |
33 | +end |
@@ -0,0 +1,167 @@ | ||
1 | +# | |
2 | +# test_link_link.rb | |
3 | +# | |
4 | +# Author : Mitsuyoshi Yoshida | |
5 | +# This program is freely distributable under the terms of an MIT-style license. | |
6 | +# | |
7 | + | |
8 | +require 'i18n' | |
9 | + | |
10 | + | |
11 | +class TestLinkKeyInfo | |
12 | + attr_reader :idno, :formatno, :enable_formats | |
13 | + | |
14 | + def initialize(linkstrs, idno=1, formatno=nil, enable_formats = nil) | |
15 | + @linkstrs = linkstrs | |
16 | + @idno = idno | |
17 | + @formatno = formatno | |
18 | + @enable_formats = enable_formats | |
19 | + end | |
20 | + | |
21 | + def linkstr(key) | |
22 | + ver = Setting.plugin_redmine_testlinklink["testlink_version"] | |
23 | + verid = nil | |
24 | + case ver | |
25 | + when '1.7' | |
26 | + verid = 0 | |
27 | + when '1.8' | |
28 | + verid = 1 | |
29 | + end | |
30 | + str = @linkstrs[verid] | |
31 | + raise sprintf(I18n.t('error.miss_ver'), key, ver) unless str | |
32 | + str | |
33 | + end | |
34 | + | |
35 | +end | |
36 | + | |
37 | + | |
38 | + | |
39 | +class TestLinkLink | |
40 | + | |
41 | + private | |
42 | + | |
43 | + KeyTable = { | |
44 | + 'case' => TestLinkKeyInfo.new(['testcases/archiveData.php?version_id=undefined&edit=testcase&id=%s', | |
45 | + 'testcases/archiveData.php?targetTestCase=%s&edit=testcase']), | |
46 | + 'suite' => TestLinkKeyInfo.new(['testcases/archiveData.php?edit=testsuite&id=%s', | |
47 | + 'testcases/archiveData.php?print_scope=test_specification&edit=testsuite&level=testsuite&id=%s']), | |
48 | + 'project' => TestLinkKeyInfo.new([nil, 'project/projectEdit.php?doAction=edit&tprojectID=%s']), | |
49 | + 'plan' => TestLinkKeyInfo.new(['plan/planEdit.php?tplan_id=%s&do_action=edit', | |
50 | + 'plan/planEdit.php?do_action=edit&tplan_id=%s']), | |
51 | + 'milestone' => TestLinkKeyInfo.new(['plan/planMilestones.php?id=%s', | |
52 | + 'plan/planMilestonesEdit.php?doAction=edit&id=%s']), | |
53 | + 'build' => TestLinkKeyInfo.new(['plan/buildNew.php?do_action=edit&build_id=%s', | |
54 | + 'plan/buildEdit.php?do_action=edit&build_id=%s']), | |
55 | + 'cfield' => TestLinkKeyInfo.new(['cfields/cfields_edit.php?do_action=edit&cfield_id=%s', | |
56 | + 'cfields/cfieldsEdit.php?do_action=edit&cfield_id=%s']), | |
57 | + 'keyword' => TestLinkKeyInfo.new(['keywords/keywordsView.php?id=%s', | |
58 | + 'keywords/keywordsEdit.php?doAction=edit&id=%s']), | |
59 | + 'user' => TestLinkKeyInfo.new(['usermanagement/usersedit.php?user_id=', | |
60 | + 'usermanagement/usersEdit.php?doAction=edit&user_id=%s']), | |
61 | + 'planreport' => TestLinkKeyInfo.new([nil, 'results/printDocument.php?level=testsuite&id=%s&type=testplan&docTestPlanId=%s'], | |
62 | + 2, 0, [1, 4]), | |
63 | + 'report' => TestLinkKeyInfo.new([nil, 'results/printDocument.php?level=testsuite&id=%s&type=testreport&docTestPlanId=%s'], | |
64 | + 2, 0, [1, 4]), | |
65 | + 'metrics' => TestLinkKeyInfo.new([nil, 'results/resultsGeneral.php?&tplan_id=%s'], 1, 0, [2,3]), | |
66 | + 'result' => TestLinkKeyInfo.new([nil, 'results/resultsTC.php?&tplan_id=%s'], 1, 0, [2,3]), | |
67 | + 'graph' => TestLinkKeyInfo.new([nil, 'results/charts.php?&tplan_id=%s'], 1, 0) | |
68 | + } | |
69 | + DefaultArgs = { | |
70 | + "planreport" => ['summary'], | |
71 | + "report" => ['summary', 'passfail'] | |
72 | + } | |
73 | + FormatNameTable = { | |
74 | + 'odt' => 1, | |
75 | + 'ods' => 2, | |
76 | + 'xls' => 3, | |
77 | + 'doc' => 4 | |
78 | + } | |
79 | + | |
80 | + def default_output_items(key) | |
81 | + out = [] | |
82 | + reg = /^default_#{key}_(\w+)$/ | |
83 | + Setting.plugin_redmine_testlinklink.each {|key, val| | |
84 | + if ((key =~ reg) and val) | |
85 | + out << $1 | |
86 | + end | |
87 | + } | |
88 | + out | |
89 | + end | |
90 | + | |
91 | + public | |
92 | + | |
93 | + def initialize(*args) | |
94 | + @ids = [] | |
95 | + @key = nil | |
96 | + @restargs = [] | |
97 | + @keyinfo = nil | |
98 | + @isdl = nil | |
99 | + @formatno = nil | |
100 | + @formatname = nil | |
101 | + args.each {|arg| | |
102 | + val = nil | |
103 | + if arg | |
104 | + val = arg.strip | |
105 | + val = nil if val.empty? | |
106 | + end | |
107 | + if (!@key) | |
108 | + @key = val | |
109 | + raise I18n.t('error.no_key') unless val | |
110 | + @keyinfo = KeyTable[val] | |
111 | + unless @keyinfo | |
112 | + raise I18n.t('error.invalid_key') | |
113 | + end | |
114 | + @formatno = @keyinfo.formatno | |
115 | + elsif (@ids.size < @keyinfo.idno) | |
116 | + raise I18n.t('error.no_id') unless val | |
117 | + @ids << val | |
118 | + else | |
119 | + @restargs << val if val | |
120 | + end | |
121 | + } | |
122 | + end | |
123 | + | |
124 | + | |
125 | + def formatname=(fmtname) | |
126 | + fmtno = FormatNameTable[fmtname] | |
127 | + unless fmtno | |
128 | + raise sprintf(I18n.t('error.invalid_fmt'), fmtname, FormatNameTable.keys.join(',')) | |
129 | + end | |
130 | + unless @keyinfo.enable_formats.include?(fmtno) | |
131 | + raise sprintf(I18n.t('error.not_report'), fmtname) | |
132 | + end | |
133 | + @formatno = fmtno | |
134 | + @formatname = fmtname | |
135 | + end | |
136 | + | |
137 | + | |
138 | + def link | |
139 | + idstr = @ids.join('-') | |
140 | + viewstr = "TestLink:#{@key}##{idstr}" | |
141 | + if (0 < @restargs.size) | |
142 | + viewstr += "(#{@restargs.join(', ')})" | |
143 | + end | |
144 | + linkstr = sprintf(@keyinfo.linkstr(@key), *@ids) | |
145 | + if (@keyinfo.idno == 2) | |
146 | + args = default_output_items(@key) + @restargs | |
147 | + linkstr += '&' + args.uniq.map{|e| e + '=y'}.join('&') | |
148 | + elsif (@key == 'result' and (0 < @restargs.size)) | |
149 | + linkstr.gsub!('resultsTC', 'resultsByStatus') | |
150 | + linkstr += '&type=' + @restargs[0] | |
151 | + end | |
152 | + linkstr += '&' + "format=#{@formatno}" if @formatno | |
153 | + | |
154 | + linkstr = "lib/" + linkstr | |
155 | + linkstr = File.join(Setting.plugin_redmine_testlinklink["testlink_address"], linkstr) | |
156 | + | |
157 | + windowstr = "target='_blank'" | |
158 | + if (@formatname) | |
159 | + windowstr = "" | |
160 | + viewstr += ":#{@formatname}" | |
161 | + end | |
162 | + | |
163 | + "<a class='testlinklink' href='#{linkstr}' #{windowstr}>#{viewstr}</a>".html_safe | |
164 | + end | |
165 | + | |
166 | + | |
167 | +end |
@@ -0,0 +1,7 @@ | ||
1 | +module RedmineTestlinklink | |
2 | + class Hooks < Redmine::Hook::ViewListener | |
3 | + def view_layouts_base_html_head(context={}) | |
4 | + stylesheet_link_tag 'testlink_link', :plugin => 'redmine_testlinklink' | |
5 | + end | |
6 | + end | |
7 | +end |
@@ -0,0 +1,6 @@ | ||
1 | +div.wiki .testlinklink { | |
2 | + background-position: 0% 60%; | |
3 | + background-repeat: no-repeat; | |
4 | + padding-left: 12px; | |
5 | + background-image: url(../images/testlink_link.png); | |
6 | +} |
@@ -0,0 +1,3 @@ | ||
1 | +.jstb_testcase { | |
2 | + background-image: url('../images/testlink.png'); | |
3 | +} |
@@ -0,0 +1,39 @@ | ||
1 | += Redmine TestLink Link Plugin | |
2 | + | |
3 | +This plug-in makes it possible to link TestLink (Test Management System) | |
4 | +from the Redmine (Bug Tracking System). | |
5 | + | |
6 | + | |
7 | +== Feature | |
8 | + | |
9 | +* Uses Wiki Macro, wherever you can use wiki notation | |
10 | +* It is possible to link to not only the test case | |
11 | + but also the project, the test planning and so on. | |
12 | +* The address of the server of TestLink can be changed in the setting page of this plugin. | |
13 | + | |
14 | + | |
15 | +== Gegging a plugin package | |
16 | + | |
17 | +{SourceForge.JP}[http://sourceforge.jp/projects/rp-testlinklink/releases/] | |
18 | + | |
19 | + | |
20 | +== Installation and Setup | |
21 | + | |
22 | +1. Extends the dawnloaded package in vender/plugins directory. | |
23 | +2. Reboot Redmine WEB server. | |
24 | +3. Open the setting page of "Redmine TestLink Link Plugin" | |
25 | +4. Change TestLink server address. (Default : http://localhost/testlink) | |
26 | +5. Set TestLink Version ("1.8" or "1.7") | |
27 | + | |
28 | +== Usage | |
29 | + | |
30 | +http://www.r-labs.org/projects/rp-testlinklink/wiki/PluginUsageEn | |
31 | + | |
32 | + | |
33 | +== Contact | |
34 | + | |
35 | +If you find a bug(Defect) or hava a Proposal, create a new issue. | |
36 | +http://www.r-labs.org/projects/rp-testlinklink/issues | |
37 | + | |
38 | +If you quest about this plugin, write the forum. | |
39 | +http://www.r-labs.org/projects/rp-testlinklink/boards | |
\ No newline at end of file |
@@ -0,0 +1,45 @@ | ||
1 | += Redmine TestLink Link プラグイン | |
2 | + | |
3 | +Redmine (バグ管理システム) から TestLink (テスト管理システム) への連携機能を提供する | |
4 | +Redmine プラグインです。 | |
5 | +Wiki マクロを使って、 TestLink のテストケース、テストプロジェクトなどへの | |
6 | +リンクを張ることができるようになります。 | |
7 | + | |
8 | + | |
9 | +== 特徴 | |
10 | + | |
11 | +* Wiki マクロを使用し、 Wiki 記法が使用できるところではどこからでも TestLink にリンクが出来ます。 | |
12 | +* テストケースだけではなく、プロジェクト、テスト計画などにもリンクできます。 | |
13 | +* プラグインの設定画面で TestLink のサーバーのアドレスを変更することが出来ます。 | |
14 | + | |
15 | + | |
16 | +== プラグインパッケージの取得 | |
17 | + | |
18 | +プラグインパッケージは以下から取得してください。 | |
19 | +* {SourceForge.JP}[http://sourceforge.jp/projects/rp-testlinklink/releases/] | |
20 | + | |
21 | + | |
22 | +== インストールと設定 | |
23 | + | |
24 | +1. 取得した圧縮ファイルを (インストールディレクトリ)/vender/plugins に展開します。 | |
25 | +2. Redmine の WEB サーバ(Apache など)を再起動します。 | |
26 | +3. トップメニューの [管理] メニューから [プラグイン] を選択し、 | |
27 | + Redmine TestLink Link Plugin の [設定] を選択します。 | |
28 | +4. 設定画面の TestLink サーバアドレスを変更します。(デフォルト : http://localhost/testlink) | |
29 | +5. TestLink のバージョンを設定します。("1.8" or "1.7") | |
30 | + | |
31 | + | |
32 | +== 使用法 | |
33 | + | |
34 | +使用法は以下をご覧ください。 | |
35 | +* http://www.r-labs.org/projects/rp-testlinklink/wiki/PluginUsage | |
36 | + | |
37 | + | |
38 | + | |
39 | +== 質問、バグ報告など | |
40 | + | |
41 | +不具合報告や要望などありましたら、以下で Defect や Proposal のチケットを発行して下さい。 | |
42 | +http://www.r-labs.org/projects/rp-testlinklink/issues | |
43 | + | |
44 | +質問などは以下のフォーラムに記述して下さい。要望などをこちらに書いてもらってもかまいません。 | |
45 | +http://www.r-labs.org/projects/rp-testlinklink/boards |
@@ -0,0 +1,31 @@ | ||
1 | +# Redmine TestLink Link | |
2 | +en: | |
3 | + label: | |
4 | + testlink_server: TestLink Server Settings | |
5 | + address: Site Address | |
6 | + version: Version | |
7 | + output_settitle: Default Output Items Setting | |
8 | + key: | |
9 | + report: Test report | |
10 | + planreport: Test plan report | |
11 | + outitem: | |
12 | + toc: Table of Contents | |
13 | + header: Test Suite description | |
14 | + summary: Test Case Summary | |
15 | + body: Test Case Scenario | |
16 | + author: Test Case Author | |
17 | + keyword: Test Case keywords | |
18 | + cfields: Test Case Custom Fields | |
19 | + passfail: Test results | |
20 | + metrics: Metrics | |
21 | + testplan: Test Plan description | |
22 | + error: | |
23 | + miss_ver: "\"%s\" is not support in TestLink %s" | |
24 | + no_id: ID is not set. | |
25 | + no_key: Key is not set. | |
26 | + invalid_key: Invalid key. | |
27 | + invalid_fmt: "\"%s\":Invalid format name. [%s]" | |
28 | + not_report: The Indentifer is not support "%s" format. | |
29 | + | |
30 | + label_tag_testcase: Link to a test case of TestLink | |
31 | + |
@@ -0,0 +1,33 @@ | ||
1 | +# Redmine TestLink Link | |
2 | +ja: | |
3 | + label: | |
4 | + testlink_server: TestLink サーバ設定 | |
5 | + address: サイトアドレス | |
6 | + version: バージョン | |
7 | + output_settitle: 省略時の出力項目の設定 | |
8 | + key: | |
9 | + report: テストレポート | |
10 | + planreport: テスト計画レポート | |
11 | + outitem: | |
12 | + toc: 目次 | |
13 | + header: テストスイートの説明 | |
14 | + summary: テストケースの要約 | |
15 | + body: 本文 | |
16 | + author: テストケース作者 | |
17 | + keyword: テストケースに関連するキーワード | |
18 | + cfields: テストケースに関連するカスタムフィールド | |
19 | + passfail: 成功/失敗と備考 | |
20 | + metrics: メトリクス | |
21 | + testplan: テスト計画の説明 | |
22 | + error: | |
23 | + miss_ver: "\"%s\" は TestLink %s では対応していません。" | |
24 | + no_id: ID が設定されていません。 | |
25 | + no_key: 識別名が設定されていません | |
26 | + invalid_key: 不適切な識別名です。 | |
27 | + invalid_fmt: "\"%s\":不適切なフォーマット名です。[%s]" | |
28 | + not_report: 指定された識別名は "%s" フォーマットでの出力はできません。 | |
29 | + | |
30 | + label_tag_testcase: TestLink のテストケースへのリンク | |
31 | + | |
32 | + | |
33 | + |