• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26var ui = ui || {};
27ui.notifications = ui.notifications || {};
28
29(function(){
30
31var kMaxTestsPerGroup = 3;
32
33ui.notifications.Stream = base.extends('ol', {
34    init: function()
35    {
36        this.className = 'notifications';
37    },
38    add: function(notification)
39    {
40        this.appendChild(notification);
41        return notification;
42    }
43});
44
45ui.notifications.Notification = base.extends('li', {
46    init: function()
47    {
48        this._how = this.appendChild(document.createElement('div'));
49        this._how.className = 'how';
50        this._what = this.appendChild(document.createElement('div'));
51        this._what.className = 'what';
52        this._index = 0;
53        $(this).hide().fadeIn('fast');
54    },
55    dismiss: function()
56    {
57        // FIXME: These fade in/out effects are lame.
58        $(this).fadeOut(function()
59        {
60            this.parentNode && this.parentNode.removeChild(this);
61        });
62    },
63});
64
65ui.notifications.Info = base.extends(ui.notifications.Notification, {
66    init: function(message)
67    {
68        this.update(message);
69    },
70    update: function(message)
71    {
72        this._what.textContent = message;
73    },
74    updateWithNode: function(node)
75    {
76        $(this._what).empty();
77        this._what.appendChild(node);
78    }
79});
80
81ui.notifications.FailingTestGroup = base.extends('li', {
82    init: function(groupName, testNameList)
83    {
84        this.appendChild(ui.createLinkNode(ui.urlForFlakinessDashboard(testNameList), groupName));
85    }
86});
87
88var Cause = base.extends('li', {
89    init: function()
90    {
91        this._description = this.appendChild(document.createElement('div'));
92        this._description.className = 'description';
93    }
94});
95
96ui.notifications.SuspiciousCommit = base.extends(Cause, {
97    init: function(commitData)
98    {
99        this._revision = commitData.revision;
100        this._description.appendChild(ui.createLinkNode(trac.changesetURL(commitData.revision), commitData.revision));
101        this._details = this._description.appendChild(document.createElement('span'));
102        this._addDetail('title', commitData);
103        this._addDetail('author', commitData);
104        this._addDetail('reviewer', commitData);
105        this._addDetail('bugID', commitData,
106            ui.urlForCrbug,
107            function(value) {
108                return value.split(/\s*,\s*/);
109            }
110        );
111    },
112    hasRevision: function(revision)
113    {
114        return this._revision == revision;
115    },
116    _addDetail: function(part, commitData, linkFunction)
117    {
118        var content = commitData[part];
119        if (!content)
120            return;
121
122        var span = this._details.appendChild(document.createElement('span'));
123        span.className = part;
124
125        if (linkFunction) {
126            var parts = $.isArray(content) ? content : [content];
127            parts.forEach(function(item, index) {
128                if (index > 0)
129                    span.appendChild(document.createTextNode(', '));
130                var link = ui.createLinkNode(linkFunction(item), item);
131                link.className = part + '-item';
132                span.appendChild(link);
133            });
134        } else {
135            span.textContent = content;
136        }
137    }
138});
139
140ui.notifications.Failure = base.extends(ui.notifications.Notification, {
141    init: function()
142    {
143        this._problem = this._what.appendChild(document.createElement('div'));
144        this._problem.className = 'problem';
145        this._effects = this._problem.appendChild(document.createElement('ul'));
146        this._effects.className = 'effects';
147        this._causes = this._what.appendChild(document.createElement('ul'));
148        this._causes.className = 'causes';
149    },
150});
151
152ui.notifications.FailingTests = base.extends(ui.notifications.Failure, {
153    init: function() {
154        // FIXME: Convert actions to a link from test!
155        this._problem.appendChild(new ui.actions.List([
156            new ui.actions.Examine().makeDefault(),
157            new ui.actions.Rebaseline(),
158        ]));
159        this._testNameList = [];
160    },
161    testNameList: function()
162    {
163        return this._testNameList;
164    },
165    containsFailureAnalysis: function(failureAnalysis)
166    {
167        return this._testNameList.indexOf(failureAnalysis.testName) != -1;
168    },
169    addFailureAnalysis: function(failureAnalysis)
170    {
171        if (this.containsFailureAnalysis(failureAnalysis))
172            return false;
173        this._testNameList.push(failureAnalysis.testName);
174        $(this._effects).empty();
175        this._forEachTestGroup(function(groupName, testNameList) {
176            this._effects.appendChild(new ui.notifications.FailingTestGroup(groupName, testNameList))
177        }.bind(this));
178        return true;
179    },
180    _forEachTestGroup: function(callback)
181    {
182        var individualTests = [];
183        base.forEachDirectory(this._testNameList, function(groupLabel, testsInDirectory) {
184            if (testsInDirectory.length <= kMaxTestsPerGroup) {
185                individualTests = individualTests.concat(testsInDirectory);
186                return;
187            }
188            callback(groupLabel, testsInDirectory);
189        });
190        individualTests.forEach(function(testName) {
191            callback(testName, [testName]);
192        });
193    }
194});
195
196ui.notifications.FailingTestsSummary = base.extends(ui.notifications.FailingTests, {
197    init: function() {
198        this._where = this._how.appendChild(new ui.failures.FailureGrid());
199        this._commitDataPinned = false;
200    },
201    purge: function() {
202        this._where.purge();
203    },
204    updateBuilderResults: function(resultNodesByBuilder)
205    {
206        this._where.update(resultNodesByBuilder);
207    },
208    addFailureAnalysis: function(failureAnalysis)
209    {
210        this.updateBuilderResults(failureAnalysis.resultNodesByBuilder);
211        if (!ui.notifications.FailingTests.prototype.addFailureAnalysis.call(this, failureAnalysis))
212            return false;
213    },
214    pinToCommitData: function(commitData)
215    {
216        if (this._commitDataPinned)
217            return;
218        this._commitDataPinned = true;
219        $(this._causes).children().each(function() {
220            if (this.hasRevision(commitData.revision))
221                return;
222            $(this).detach();
223        });
224    },
225    addCommitData: function(commitData)
226    {
227        if (this._commitDataPinned)
228            return null;
229        return this._causes.appendChild(new ui.notifications.SuspiciousCommit(commitData));
230    }
231});
232
233ui.notifications.BuildersFailing = base.extends(ui.notifications.Failure, {
234    init: function(message)
235    {
236        if (message)
237            this._problem.insertBefore(document.createTextNode(message + ':'), this._problem.firstChild);
238    },
239    setFailingBuilders: function(failuresList)
240    {
241        $(this._effects).empty().append(Object.keys(failuresList).map(function(builderName) {
242            var effect = document.createElement('li');
243            effect.className = 'builder';
244            effect.appendChild(new ui.failures.Builder(builderName, failuresList[builderName]));
245            return effect;
246        }));
247    }
248});
249
250})();
251