зеркало из https://github.com/mozilla/treeherder.git
Bug 1576966 - Convert filtering selenium tests to React Testing Library
This commit is contained in:
Родитель
f05196f36b
Коммит
56f2c5ca78
|
@ -1,35 +0,0 @@
|
|||
import pytest
|
||||
|
||||
from pages.treeherder import Treeherder
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def commits(create_push, create_commit, test_repository):
|
||||
commit = create_commit(create_push(test_repository))
|
||||
create_commit(create_push(
|
||||
test_repository, revision=commit.revision[::-1], author='bar@foo.com'))
|
||||
|
||||
|
||||
def test_filter_jobs_by_author(base_url, selenium, commits):
|
||||
page = Treeherder(selenium, base_url).open()
|
||||
page.wait.until(lambda _: len(page.pushes) == 2)
|
||||
# check authors are distinct
|
||||
assert len(set(push.author for push in page.pushes)) == 2
|
||||
author = page.pushes[-1].author
|
||||
page.pushes[-1].filter_by_author()
|
||||
page.wait.until(lambda _: len(page.pushes) == 1)
|
||||
assert page.pushes[0].author == author
|
||||
assert len(page.active_filters.filters) == 1
|
||||
assert page.active_filters.filters[0].field == 'author:'
|
||||
assert page.active_filters.filters[0].value == author.split('@')[0]
|
||||
|
||||
|
||||
def test_clear_filter_jobs_by_author(base_url, selenium, commits):
|
||||
page = Treeherder(selenium, base_url).open()
|
||||
page.wait.until(lambda _: len(page.pushes) == 2)
|
||||
page.pushes[0].filter_by_author()
|
||||
page.wait.until(lambda _: len(page.pushes) == 1)
|
||||
page.active_filters.filters[0].clear()
|
||||
page.wait.until(lambda _: len(page.pushes) == 2)
|
||||
# check authors are distinct
|
||||
assert len(set(push.author for push in page.pushes)) == 2
|
|
@ -1,28 +0,0 @@
|
|||
import pytest
|
||||
|
||||
from pages.treeherder import Treeherder
|
||||
|
||||
RESULTS = ['testfailed', 'busted', 'exception']
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_jobs(eleven_job_blobs, create_jobs):
|
||||
for i, status in enumerate(RESULTS):
|
||||
eleven_job_blobs[i]['job']['result'] = status
|
||||
return create_jobs(eleven_job_blobs[0:len(RESULTS)])
|
||||
|
||||
|
||||
@pytest.mark.parametrize('result', RESULTS)
|
||||
def test_filter_jobs_by_failure_result(base_url, selenium, test_jobs, result):
|
||||
page = Treeherder(selenium, base_url).open()
|
||||
page.wait.until(lambda _: len(page.all_jobs) == len(test_jobs))
|
||||
assert len(page.all_jobs) == len(RESULTS)
|
||||
with page.filters_menu() as filters:
|
||||
for result in RESULTS:
|
||||
getattr(filters, 'toggle_{}_jobs'.format(result))()
|
||||
assert len(page.all_jobs) == 0
|
||||
with page.filters_menu() as filters:
|
||||
getattr(filters, 'toggle_{}_jobs'.format(result))()
|
||||
assert len(page.all_jobs) == 1
|
||||
page.all_jobs[0].click()
|
||||
assert page.details_panel.job_details.result == result
|
|
@ -1,40 +0,0 @@
|
|||
import pytest
|
||||
|
||||
from pages.treeherder import Treeherder
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_jobs(eleven_job_blobs, create_jobs):
|
||||
for i, platform in enumerate(['linux32', 'windowsxp']):
|
||||
eleven_job_blobs[i]['job']['machine_platform']['platform'] = platform
|
||||
return create_jobs(eleven_job_blobs[0:2])
|
||||
|
||||
|
||||
@pytest.mark.parametrize('method', [('keyboard'), ('pointer')])
|
||||
def test_filter_jobs_by_keywords(base_url, selenium, test_jobs, method):
|
||||
page = Treeherder(selenium, base_url).open()
|
||||
page.wait.until(lambda _: len(page.all_jobs) == len(test_jobs))
|
||||
page.filter_by('linux', method)
|
||||
page.wait.until(lambda _: len(page.all_jobs) == 1)
|
||||
|
||||
|
||||
def test_filter_jobs_by_keywords_from_job_panel(base_url, selenium, test_jobs):
|
||||
page = Treeherder(selenium, base_url).open()
|
||||
page.wait.until(lambda _: len(page.all_jobs) == len(test_jobs))
|
||||
page.all_jobs[0].click()
|
||||
keywords = page.details_panel.job_details.keywords
|
||||
page.details_panel.job_details.filter_by_keywords()
|
||||
page.wait.until(lambda _: len(page.all_jobs) < len(test_jobs))
|
||||
assert page.quick_filter_term == keywords.lower()
|
||||
|
||||
|
||||
# See https://bugzilla.mozilla.org/show_bug.cgi?id=1575835 to re-enable
|
||||
@pytest.mark.skip(reason="The test times out too often and prevents deployments")
|
||||
@pytest.mark.parametrize('method', [('keyboard'), ('pointer')])
|
||||
def test_clear_filter(base_url, selenium, test_jobs, method):
|
||||
page = Treeherder(selenium, base_url).open()
|
||||
page.wait.until(lambda _: len(page.all_jobs) == len(test_jobs))
|
||||
page.filter_by('linux')
|
||||
page.wait.until(lambda _: len(page.all_jobs) == 1)
|
||||
page.clear_filter(method)
|
||||
page.wait.until(lambda _: len(page.all_jobs) == len(test_jobs))
|
|
@ -1,100 +0,0 @@
|
|||
import pytest
|
||||
|
||||
from pages.treeherder import Treeherder
|
||||
|
||||
JOB_DATA = [
|
||||
{'result': 'testfailed'},
|
||||
{'result': 'success'},
|
||||
{'result': 'retry'},
|
||||
{'result': 'usercancel'},
|
||||
{'result': 'superseded'},
|
||||
{'result': 'unknown', 'state': 'running'}]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_jobs(eleven_job_blobs, create_jobs):
|
||||
job_blobs = [j for j in eleven_job_blobs if 'superseded' not in j]
|
||||
for i, job in enumerate(JOB_DATA):
|
||||
job_blobs[i]['job'].update(job)
|
||||
return create_jobs(job_blobs[0:len(JOB_DATA)])
|
||||
|
||||
|
||||
def test_default_filters(base_url, selenium, test_jobs):
|
||||
"""Show superseded, and verify all test jobs are displayed."""
|
||||
page = Treeherder(selenium, base_url).open()
|
||||
page.toggle_superseded() # defaults to hidden
|
||||
page.wait.until(lambda _: len(page.all_jobs) == len(test_jobs))
|
||||
|
||||
|
||||
def test_filter_failures(base_url, selenium, test_jobs):
|
||||
"""Hide all except failures and verify job is displayed."""
|
||||
page = Treeherder(selenium, base_url).open()
|
||||
page.toggle_success()
|
||||
page.toggle_retry()
|
||||
page.toggle_usercancel()
|
||||
page.toggle_in_progress()
|
||||
page.wait.until(lambda _: len(page.all_jobs) == 1)
|
||||
page.all_jobs[0].click()
|
||||
assert page.details_panel.job_details.result == 'testfailed'
|
||||
|
||||
|
||||
def test_filter_success(base_url, selenium, test_jobs):
|
||||
"""Hide all except success and verify job is displayed."""
|
||||
page = Treeherder(selenium, base_url).open()
|
||||
page.toggle_failures()
|
||||
page.toggle_retry()
|
||||
page.toggle_usercancel()
|
||||
page.toggle_in_progress()
|
||||
page.wait.until(lambda _: len(page.all_jobs) == 1)
|
||||
page.all_jobs[0].click()
|
||||
assert page.details_panel.job_details.result == 'success'
|
||||
|
||||
|
||||
def test_filter_retry(base_url, selenium, test_jobs):
|
||||
"""Hide all except verify and verify job is displayed."""
|
||||
page = Treeherder(selenium, base_url).open()
|
||||
page.toggle_success()
|
||||
page.toggle_failures()
|
||||
page.toggle_usercancel()
|
||||
page.toggle_in_progress()
|
||||
page.wait.until(lambda _: len(page.all_jobs) == 1)
|
||||
page.all_jobs[0].click()
|
||||
assert page.details_panel.job_details.result == 'retry'
|
||||
|
||||
|
||||
def test_filter_usercancel(base_url, selenium, test_jobs):
|
||||
"""Hide all except usercancel and verify job is displayed."""
|
||||
page = Treeherder(selenium, base_url).open()
|
||||
page.toggle_success()
|
||||
page.toggle_failures()
|
||||
page.toggle_retry()
|
||||
page.toggle_in_progress()
|
||||
page.wait.until(lambda _: len(page.all_jobs) == 1)
|
||||
page.all_jobs[0].click()
|
||||
assert page.details_panel.job_details.result == 'usercancel'
|
||||
|
||||
|
||||
def test_filter_superseded(base_url, selenium, test_jobs):
|
||||
"""Hide all except superseded and verify job is displayed."""
|
||||
page = Treeherder(selenium, base_url).open()
|
||||
page.toggle_success()
|
||||
page.toggle_failures()
|
||||
page.toggle_retry()
|
||||
page.toggle_usercancel()
|
||||
page.toggle_superseded() # defaults to hidden
|
||||
page.toggle_in_progress()
|
||||
page.wait.until(lambda _: len(page.all_jobs) == 1)
|
||||
page.all_jobs[0].click()
|
||||
assert page.details_panel.job_details.result == 'superseded'
|
||||
|
||||
|
||||
def test_filter_in_progress(base_url, selenium, test_jobs):
|
||||
"""Hide all except in_progress and verify job is displayed."""
|
||||
page = Treeherder(selenium, base_url).open()
|
||||
page.toggle_success()
|
||||
page.toggle_failures()
|
||||
page.toggle_retry()
|
||||
page.toggle_usercancel()
|
||||
page.wait.until(lambda _: len(page.all_jobs) == 1)
|
||||
page.all_jobs[0].click()
|
||||
assert page.details_panel.job_details.result == 'unknown'
|
|
@ -1,20 +0,0 @@
|
|||
import pytest
|
||||
|
||||
from pages.treeherder import Treeherder
|
||||
|
||||
RESULTS = ['testfailed', 'busted', 'exception']
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_jobs(eleven_job_blobs, create_jobs):
|
||||
results = ['success'] + RESULTS
|
||||
for i, status in enumerate(results):
|
||||
eleven_job_blobs[i]['job']['result'] = status
|
||||
return create_jobs(eleven_job_blobs[0:len(results)])
|
||||
|
||||
|
||||
def test_filter_unclassified_jobs(base_url, selenium, test_jobs):
|
||||
page = Treeherder(selenium, base_url).open()
|
||||
page.wait.until(lambda _: len(page.all_jobs) == len(test_jobs))
|
||||
page.filter_unclassified_jobs()
|
||||
assert len(page.all_jobs) == len(RESULTS)
|
|
@ -0,0 +1,281 @@
|
|||
import React from 'react';
|
||||
import { fetchMock } from 'fetch-mock';
|
||||
import {
|
||||
render,
|
||||
cleanup,
|
||||
fireEvent,
|
||||
waitForElement,
|
||||
waitForElementToBeRemoved,
|
||||
} from '@testing-library/react';
|
||||
|
||||
import App from '../../../ui/job-view/App';
|
||||
import reposFixture from '../mock/repositories';
|
||||
import pushListFixture from '../mock/push_list';
|
||||
import { getApiUrl } from '../../../ui/helpers/url';
|
||||
import {
|
||||
getProjectUrl,
|
||||
replaceLocation,
|
||||
setUrlParam,
|
||||
} from '../../../ui/helpers/location';
|
||||
import jobListFixtureOne from '../mock/job_list/job_1';
|
||||
import jobMap from '../mock/job_map';
|
||||
|
||||
describe('Filtering', () => {
|
||||
const repoName = 'autoland';
|
||||
|
||||
beforeAll(() => {
|
||||
fetchMock.get('/revision.txt', []);
|
||||
fetchMock.get(getApiUrl('/repository/'), reposFixture);
|
||||
fetchMock.get(getApiUrl('/user/'), []);
|
||||
fetchMock.get(getApiUrl('/failureclassification/'), []);
|
||||
// ``begin:`` here will match any fetch call to an API that begins with
|
||||
// this string.
|
||||
fetchMock.get('begin:https://treestatus.mozilla-releng.net/trees/', {
|
||||
result: {
|
||||
message_of_the_day: '',
|
||||
reason: '',
|
||||
status: 'open',
|
||||
tree: repoName,
|
||||
},
|
||||
});
|
||||
|
||||
fetchMock.get(
|
||||
getProjectUrl('/push/?full=true&count=10', repoName),
|
||||
pushListFixture,
|
||||
);
|
||||
fetchMock.get(getProjectUrl('/push/?full=true&count=10', 'try'), {
|
||||
results: [
|
||||
{
|
||||
id: 111111,
|
||||
revision: '3333333333335143b8df3f4b3e9b504dfbc589a0',
|
||||
author: 'whozat@gmail.com',
|
||||
revision_count: 1,
|
||||
push_timestamp: 1562867957,
|
||||
repository_id: 4,
|
||||
revisions: [
|
||||
{
|
||||
repository_id: 4,
|
||||
revision: '3333333333335143b8df3f4b3e9b504dfbc589a0',
|
||||
author: 'whozat <whozat@gmail.com>',
|
||||
comments: 'didathing',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
fetchMock.get(`begin:${getApiUrl('/jobs/')}`, jobListFixtureOne);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
replaceLocation({});
|
||||
});
|
||||
|
||||
const jobCount = () => document.querySelectorAll('.job-btn').length;
|
||||
|
||||
describe('by author', () => {
|
||||
beforeEach(() => {
|
||||
fetchMock.get(
|
||||
getProjectUrl('/push/?full=true&count=10&author=reviewbot', 'autoland'),
|
||||
{
|
||||
results: [
|
||||
{
|
||||
id: 111111,
|
||||
revision: '3333333333335143b8df3f4b3e9b504dfbc589a0',
|
||||
author: 'reviewbot',
|
||||
revision_count: 1,
|
||||
push_timestamp: 1562867957,
|
||||
repository_id: 4,
|
||||
revisions: [
|
||||
{
|
||||
repository_id: 4,
|
||||
revision: '3333333333335143b8df3f4b3e9b504dfbc589a0',
|
||||
author: 'reviewbot <reviewbot>',
|
||||
comments: 'didathing',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test('should have 1 push', async () => {
|
||||
const { getAllByText, getByTestId } = render(<App />);
|
||||
// wait till the ``reviewbot`` authored push is shown before filtering.
|
||||
await waitForElement(() => getAllByText('reviewbot'));
|
||||
setUrlParam('author', 'reviewbot');
|
||||
await waitForElementToBeRemoved(() => getByTestId('push-511138'));
|
||||
|
||||
const filteredPushes = await waitForElement(() =>
|
||||
getAllByText('View Tests'),
|
||||
);
|
||||
expect(filteredPushes).toHaveLength(1);
|
||||
|
||||
setUrlParam('author', null);
|
||||
await waitForElement(() => getAllByText('jarilvalenciano@gmail.com'));
|
||||
const unFilteredPushes = await waitForElement(() =>
|
||||
getAllByText('View Tests'),
|
||||
);
|
||||
expect(unFilteredPushes).toHaveLength(10);
|
||||
});
|
||||
});
|
||||
|
||||
describe('by failure result', () => {
|
||||
beforeEach(() => {
|
||||
// polling.. Return nothing...
|
||||
fetchMock.get(
|
||||
`begin:${getProjectUrl(
|
||||
'/push/?full=true&count=11&push_timestamp__lte=',
|
||||
'autoland',
|
||||
)}`,
|
||||
{
|
||||
results: [],
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test('should have 10 failures', async () => {
|
||||
const { getAllByText, getByTitle, findAllByText } = render(<App />);
|
||||
await waitForElement(() => findAllByText('B'));
|
||||
const unclassifiedOnlyButton = getByTitle(
|
||||
'Loaded failures / toggle filtering for unclassified failures',
|
||||
);
|
||||
fireEvent.click(unclassifiedOnlyButton);
|
||||
|
||||
// Since yaml is not an unclassified failure, making this call will
|
||||
// ensure that the filtering has completed. Then we can get an accurate
|
||||
// count of what's left.
|
||||
await waitForElementToBeRemoved(() => getAllByText('yaml'));
|
||||
|
||||
// The api returns the same joblist for each push.
|
||||
// 10 pushes with 2 failures each, but only 1 unclassified.
|
||||
expect(jobCount()).toBe(10);
|
||||
|
||||
// undo the filtering and make sure we see all the jobs again
|
||||
fireEvent.click(unclassifiedOnlyButton);
|
||||
await waitForElement(() => getAllByText('yaml'));
|
||||
expect(jobCount()).toBe(40);
|
||||
});
|
||||
});
|
||||
|
||||
describe('by keywords', () => {
|
||||
beforeAll(() => {
|
||||
fetchMock.get(
|
||||
getProjectUrl('/jobs/259537372/', 'autoland'),
|
||||
Object.values(jobMap)[0],
|
||||
);
|
||||
fetchMock.get(
|
||||
getProjectUrl('/job-log-url/?job_id=259537372', 'autoland'),
|
||||
[],
|
||||
);
|
||||
fetchMock.get(
|
||||
getProjectUrl('/performance/data/?job_id=259537372', 'autoland'),
|
||||
[],
|
||||
);
|
||||
fetchMock.get(getApiUrl('/jobdetail/?job_id=259537372'), { results: [] });
|
||||
fetchMock.get(getProjectUrl('/note/?job_id=259537372', 'autoland'), []);
|
||||
fetchMock.get(
|
||||
getProjectUrl('/bug-job-map/?job_id=259537372', 'autoland'),
|
||||
[],
|
||||
);
|
||||
fetchMock.get(
|
||||
getProjectUrl('/jobs/259537372/bug_suggestions/', 'autoland'),
|
||||
[],
|
||||
);
|
||||
fetchMock.get(
|
||||
getProjectUrl('/jobs/259537372/text_log_steps/', 'autoland'),
|
||||
[],
|
||||
);
|
||||
});
|
||||
|
||||
const setFilterText = (filterField, text) => {
|
||||
fireEvent.click(filterField);
|
||||
fireEvent.change(filterField, { target: { value: text } });
|
||||
fireEvent.keyDown(filterField, { key: 'Enter' });
|
||||
};
|
||||
|
||||
test('string "yaml" should have 10 jobs', async () => {
|
||||
const { getAllByText, findAllByText } = render(<App />);
|
||||
await waitForElement(() => findAllByText('B'));
|
||||
const filterField = document.querySelector('#quick-filter');
|
||||
setFilterText(filterField, 'yaml');
|
||||
|
||||
await waitForElementToBeRemoved(() => getAllByText('B'));
|
||||
expect(jobCount()).toBe(10);
|
||||
|
||||
// undo the filtering and make sure we see all the jobs again
|
||||
setFilterText(filterField, null);
|
||||
await waitForElement(() => getAllByText('B'));
|
||||
expect(jobCount()).toBe(40);
|
||||
});
|
||||
|
||||
test('click signature should have 10 jobs', async () => {
|
||||
const { getByText, getByTitle, findAllByText } = render(<App />);
|
||||
const build = await waitForElement(() => findAllByText('B'));
|
||||
|
||||
fireEvent.mouseDown(build[0]);
|
||||
const sigLink = await waitForElement(() => getByText('(sig)'));
|
||||
expect(sigLink.getAttribute('href')).toBe(
|
||||
'/#/jobs?repo=autoland&selectedJob=259537372&searchStr=2aa083621bb989d6acf1151667288d5fe9616178',
|
||||
);
|
||||
|
||||
const keywordLink = await waitForElement(() =>
|
||||
getByTitle('Filter jobs containing these keywords'),
|
||||
);
|
||||
expect(keywordLink.getAttribute('href')).toBe(
|
||||
'/#/jobs?repo=autoland&selectedJob=259537372&searchStr=gecko%2Cdecision%2Ctask%2Copt%2Cgecko%2Cdecision%2Ctask%2C%28d%29',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('by result status', () => {
|
||||
const clickFilterChicklet = color => {
|
||||
fireEvent.click(document.querySelector(`.btn-${color}-filter-chicklet`));
|
||||
};
|
||||
|
||||
test('uncheck success should leave 30 jobs', async () => {
|
||||
const { getAllByText, findAllByText } = render(<App />);
|
||||
await waitForElement(() => findAllByText('B'));
|
||||
clickFilterChicklet('green');
|
||||
|
||||
await waitForElementToBeRemoved(() => getAllByText('D'));
|
||||
expect(jobCount()).toBe(30);
|
||||
|
||||
// undo the filtering and make sure we see all the jobs again
|
||||
clickFilterChicklet('green');
|
||||
await waitForElement(() => getAllByText('D'));
|
||||
expect(jobCount()).toBe(40);
|
||||
});
|
||||
|
||||
test('uncheck failures should leave 20 jobs', async () => {
|
||||
const { getAllByText, findAllByText } = render(<App />);
|
||||
const symbolToRemove = 'B';
|
||||
await waitForElement(() => findAllByText(symbolToRemove));
|
||||
clickFilterChicklet('red');
|
||||
|
||||
await waitForElementToBeRemoved(() => getAllByText(symbolToRemove));
|
||||
expect(jobCount()).toBe(20);
|
||||
|
||||
// undo the filtering and make sure we see all the jobs again
|
||||
clickFilterChicklet('red');
|
||||
await waitForElement(() => getAllByText(symbolToRemove));
|
||||
expect(jobCount()).toBe(40);
|
||||
});
|
||||
|
||||
test('uncheck in progress should leave 20 jobs', async () => {
|
||||
const { getAllByText, findAllByText } = render(<App />);
|
||||
const symbolToRemove = 'yaml';
|
||||
await waitForElement(() => findAllByText('B'));
|
||||
clickFilterChicklet('dkgray');
|
||||
|
||||
await waitForElementToBeRemoved(() => getAllByText(symbolToRemove));
|
||||
expect(jobCount()).toBe(30);
|
||||
|
||||
// undo the filtering and make sure we see all the jobs again
|
||||
clickFilterChicklet('dkgray');
|
||||
await waitForElement(() => getAllByText(symbolToRemove));
|
||||
expect(jobCount()).toBe(40);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -250,7 +250,7 @@ describe('Pushes Redux store', () => {
|
|||
});
|
||||
|
||||
test('should get new unclassified counts with recalculateUnclassifiedCounts', async () => {
|
||||
setUrlParam('job_type_symbol', 'cpp');
|
||||
setUrlParam('job_type_symbol', 'B');
|
||||
const { data: jobList } = await JobModel.getList({ push_id: 1 });
|
||||
|
||||
const state = reducer(
|
||||
|
@ -261,7 +261,7 @@ describe('Pushes Redux store', () => {
|
|||
const reduced = reducer(state, { type: RECALCULATE_UNCLASSIFIED_COUNTS });
|
||||
|
||||
expect(Object.keys(reduced.jobMap)).toHaveLength(4);
|
||||
expect(reduced.allUnclassifiedFailureCount).toEqual(2);
|
||||
expect(reduced.allUnclassifiedFailureCount).toEqual(1);
|
||||
expect(reduced.filteredUnclassifiedFailureCount).toEqual(1);
|
||||
});
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
"102210fe594ee9b33d82058545b1ed14f4c8206e",
|
||||
"gecko-decision",
|
||||
"opt",
|
||||
526443,
|
||||
511138,
|
||||
"success",
|
||||
"2aa083621bb989d6acf1151667288d5fe9616178",
|
||||
"completed",
|
||||
|
@ -33,7 +33,7 @@
|
|||
"32faaecac742100f7753f0c1d0aa0add01b4046b",
|
||||
"android-4-0-armv7-api16",
|
||||
"debug",
|
||||
526443,
|
||||
511138,
|
||||
"busted",
|
||||
"e2e58eb7f14af83019d3f8433c0642dde8082c4d",
|
||||
"completed",
|
||||
|
@ -51,15 +51,15 @@
|
|||
"102210fe594ee9b33d82058545b1ed14f4c8206e",
|
||||
"lint",
|
||||
"opt",
|
||||
526443,
|
||||
"success",
|
||||
511138,
|
||||
"unknown",
|
||||
"306fd1e8d922922cd171fa31f0d914300ff52228",
|
||||
"completed",
|
||||
"running",
|
||||
1
|
||||
],
|
||||
[
|
||||
2,
|
||||
1,
|
||||
4,
|
||||
259539664,
|
||||
"unknown",
|
||||
"?",
|
||||
|
@ -69,7 +69,7 @@
|
|||
"32faaecac742100f7753f0c1d0aa0add01b4046b",
|
||||
"android-hw-p2-8-0-arm7-api-16",
|
||||
"debug",
|
||||
526443,
|
||||
511138,
|
||||
"testfailed",
|
||||
"6862263481704547b805af8ba944438e1a6e63e9",
|
||||
"completed",
|
||||
|
|
Загрузка…
Ссылка в новой задаче