Single Page Tests


Single Page Tests are Calibre tests for a single page, from a single device. The aim is to provide fast feedback directly in your command line terminal or as part of a Continuous integration or deployment pipeline.

Each Single Page Tests is a totally independent report for a single page. There is no connection to single page tests and sites within your account. You can use either independently.

Every Single Page Test has a secure URL which can be publicly-accessible (no login required) or restricted to logged-in members of your team.

Create a page test

Required API Permission: Create Page Tests
tip
Tests can be run from different locations around the globe, using a range of device emulation and connection options. Experiment with the --location,--device and --connection flags.
1# This command will block until the test has been completed
2calibre test create https://calibreapp.com/ --location=Sydney --device=MotorolaMotoG4 --connection=emergingMarkets --private
1#!/usr/bin/env node
2
3const { Test } = require('calibre')
4
5const createTest = async () => {
6 // Required
7 const url = 'https://calibreapp.com/features/cli'
8 const location = 'Sydney'
9
10 // Optional
11 const device = 'iPhone8'
12 const connection = 'good3G'
13 const cookies = [
14 {
15 name: 'app.uid',
16 value: 'my-secret-tokens',
17 domain: 'calibreapp.com',
18 path: '/',
19 secure: true,
20 httpOnly: true
21 }
22 ]
23 const headers = [
24 {
25 name: 'User-Agent',
26 value: 'My Custom User Agent'
27 }
28 ]
29 const isPrivate = true
30
31 // Create the test
32 const { uuid } = await Test.create({
33 url,
34 location,
35 device,
36 connection,
37 cookies,
38 headers,
39 isPrivate
40 })
41
42 console.log(`Test created, ID: ${uuid}`)
43
44 // Wait for the test to be run
45 const results = await Test.waitForTest(uuid)
46
47 // Output the formatted JSON response
48 console.log(JSON.stringify(results, null, 2))
49}
50
51createTest()
Example response
1πŸ‡ΊπŸ‡Έ North Virginia, USA
2
34:11pm 25-Jul-2019
4
5Overall scores
6
7CATEGORY | SCORE
8Performance | 75
9Best Practices | 93
10Accessibility | 76
11SEO | 91
12Progressive Web App | 42
13
14Timing
15
16Time to First Byte
17β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β–  402 ms
18
19Response time
20β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β–  445 ms
21
22First Contentful Paint
23β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β–  1.50 sec
24
25Time to Interactive
26β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β–  7.41 sec
27
28Number of requests: 45
29
30Total Page transferred: 730.99 KB
31
32View the full report https://calibreapp.com/tests/dfa1a00/9f0cb96
1{
2 "uuid": "dfa1a00",
3 "url": "https://calibreapp.com",
4 "formattedTestUrl": "https://calibreapp.com/tests/dfa1a00/9f0cb96",
5 "status": "completed",
6 "updatedAt": "2019-07-25T06:11:09Z",
7 "adBlockerIsEnabled": false,
8 "runtimeError": {},
9 "metrics": [
10 {
11 "name": "json_body_size_in_bytes",
12 "label": "Total JSON size in bytes",
13 "value": 15383
14 },
15 {
16 "name": "json_size_in_bytes",
17 "label": "Total JSON transferred",
18 "value": 11483
19 },
20 {
21 "name": "image_body_size_in_bytes",
22 "label": "Total Image size in bytes",
23 "value": 238120
24 },
25 {
26 "name": "image_size_in_bytes",
27 "label": "Total Image transferred",
28 "value": 77077
29 },
30 {
31 "name": "font_body_size_in_bytes",
32 "label": "Total Webfont size in bytes",
33 "value": 110125
34 },
35 {
36 "name": "font_size_in_bytes",
37 "label": "Total Webfont transferred",
38 "value": 111548
39 },
40 {
41 "name": "js_body_size_in_bytes",
42 "label": "Total JavaScript size in bytes",
43 "value": 2153354
44 },
45 {
46 "name": "js_size_in_bytes",
47 "label": "Total JavaScript Transferred",
48 "value": 516164
49 },
50 {
51 "name": "css_body_size_in_bytes",
52 "label": "Total CSS size in bytes",
53 "value": 80451
54 },
55 {
56 "name": "css_size_in_bytes",
57 "label": "Total CSS transferred",
58 "value": 17460
59 },
60 {
61 "name": "html_body_size_in_bytes",
62 "label": "Total HTML size in bytes",
63 "value": 24987
64 },
65 {
66 "name": "html_size_in_bytes",
67 "label": "Total HTML transferred",
68 "value": 10680
69 },
70 {
71 "name": "page_wait_timing",
72 "label": "Response time",
73 "value": 445
74 },
75 {
76 "name": "page_size_in_bytes",
77 "label": "Total Page transferred",
78 "value": 748537
79 },
80 {
81 "name": "page_body_size_in_bytes",
82 "label": "Total Page size in bytes",
83 "value": 2624120
84 },
85 {
86 "name": "asset_count",
87 "label": "Number of requests",
88 "value": 45
89 },
90 {
91 "name": "onload",
92 "label": "onLoad",
93 "value": 2572
94 },
95 {
96 "name": "oncontentload",
97 "label": "onContentLoad",
98 "value": 1671
99 },
100 {
101 "name": "lighthouse-seo-score",
102 "label": "Lighthouse SEO Score",
103 "value": 91
104 },
105 {
106 "name": "lighthouse-best-practices-score",
107 "label": "Lighthouse Best Practices Score",
108 "value": 93
109 },
110 {
111 "name": "lighthouse-accessibility-score",
112 "label": "Lighthouse Accessibility Score",
113 "value": 76
114 },
115 {
116 "name": "lighthouse-performance-score",
117 "label": "Lighthouse Performance Score",
118 "value": 75
119 },
120 {
121 "name": "lighthouse-pwa-score",
122 "label": "Lighthouse Progressive Web App Score",
123 "value": 42
124 },
125 {
126 "name": "visually_complete_85",
127 "label": "85% Visually Complete",
128 "value": 1872
129 },
130 {
131 "name": "visually_complete",
132 "label": "Visually Complete",
133 "value": 9288
134 },
135 {
136 "name": "consistently-interactive",
137 "label": "Time to Interactive",
138 "value": 7408
139 },
140 {
141 "name": "first-interactive",
142 "label": "First CPU Idle",
143 "value": 7408
144 },
145 {
146 "name": "time-to-first-byte",
147 "label": "Time to First Byte",
148 "value": 402
149 },
150 {
151 "name": "speed_index",
152 "label": "Speed Index",
153 "value": 1822
154 },
155 {
156 "name": "first-meaningful-paint",
157 "label": "First Meaningful Paint",
158 "value": 1504
159 },
160 {
161 "name": "first-contentful-paint",
162 "label": "First Contentful Paint",
163 "value": 1504
164 },
165 {
166 "name": "firstRender",
167 "label": "First Paint",
168 "value": 1504
169 }
170 ],
171 "device": {
172 "title": "Motorola Moto G4"
173 },
174 "connection": {
175 "title": "Emerging Markets 3G"
176 },
177 "location": {
178 "name": "North Virginia, USA",
179 "emoji": "πŸ‡ΊπŸ‡Έ"
180 }
181}

View an existing test

Required API Permission: Read Page Tests
1# Pro tip: Add the --json flag for JSON output
2calibre test show <uuid>
1#!/usr/bin/env node
2
3const { Test } = require('calibre')
4
5const getTestData = async () => {
6 // Required
7 const uuid = 'dfa1a00'
8
9 // Fetch the test results
10 const results = await Test.getTestByUuid(uuid)
11
12 // Output the formatted JSON response
13 console.log(JSON.stringify(results, null, 2))
14}
15
16getTestData()
Example response
1πŸ‡ΊπŸ‡Έ North Virginia, USA
2
34:11pm 25-Jul-2019
4
5Overall scores
6
7CATEGORY | SCORE
8Performance | 75
9Best Practices | 93
10Accessibility | 76
11SEO | 91
12Progressive Web App | 42
13
14Timing
15
16Time to First Byte
17β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β–  402 ms
18
19Response time
20β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β–  445 ms
21
22First Contentful Paint
23β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β–  1.50 sec
24
25Time to Interactive
26β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β–  7.41 sec
27
28Number of requests: 45
29
30Total Page transferred: 730.99 KB
31
32View the full report https://calibreapp.com/tests/dfa1a00/9f0cb96
1{
2 "uuid": "dfa1a00",
3 "url": "https://calibreapp.com",
4 "formattedTestUrl": "https://calibreapp.com/tests/dfa1a00/9f0cb96",
5 "status": "completed",
6 "updatedAt": "2019-07-25T06:11:09Z",
7 "adBlockerIsEnabled": false,
8 "runtimeError": {},
9 "metrics": [
10 {
11 "name": "json_body_size_in_bytes",
12 "label": "Total JSON size in bytes",
13 "value": 15383
14 },
15 {
16 "name": "json_size_in_bytes",
17 "label": "Total JSON transferred",
18 "value": 11483
19 },
20 {
21 "name": "image_body_size_in_bytes",
22 "label": "Total Image size in bytes",
23 "value": 238120
24 },
25 {
26 "name": "image_size_in_bytes",
27 "label": "Total Image transferred",
28 "value": 77077
29 },
30 {
31 "name": "font_body_size_in_bytes",
32 "label": "Total Webfont size in bytes",
33 "value": 110125
34 },
35 {
36 "name": "font_size_in_bytes",
37 "label": "Total Webfont transferred",
38 "value": 111548
39 },
40 {
41 "name": "js_body_size_in_bytes",
42 "label": "Total JavaScript size in bytes",
43 "value": 2153354
44 },
45 {
46 "name": "js_size_in_bytes",
47 "label": "Total JavaScript Transferred",
48 "value": 516164
49 },
50 {
51 "name": "css_body_size_in_bytes",
52 "label": "Total CSS size in bytes",
53 "value": 80451
54 },
55 {
56 "name": "css_size_in_bytes",
57 "label": "Total CSS transferred",
58 "value": 17460
59 },
60 {
61 "name": "html_body_size_in_bytes",
62 "label": "Total HTML size in bytes",
63 "value": 24987
64 },
65 {
66 "name": "html_size_in_bytes",
67 "label": "Total HTML transferred",
68 "value": 10680
69 },
70 {
71 "name": "page_wait_timing",
72 "label": "Response time",
73 "value": 445
74 },
75 {
76 "name": "page_size_in_bytes",
77 "label": "Total Page transferred",
78 "value": 748537
79 },
80 {
81 "name": "page_body_size_in_bytes",
82 "label": "Total Page size in bytes",
83 "value": 2624120
84 },
85 {
86 "name": "asset_count",
87 "label": "Number of requests",
88 "value": 45
89 },
90 {
91 "name": "onload",
92 "label": "onLoad",
93 "value": 2572
94 },
95 {
96 "name": "oncontentload",
97 "label": "onContentLoad",
98 "value": 1671
99 },
100 {
101 "name": "lighthouse-seo-score",
102 "label": "Lighthouse SEO Score",
103 "value": 91
104 },
105 {
106 "name": "lighthouse-best-practices-score",
107 "label": "Lighthouse Best Practices Score",
108 "value": 93
109 },
110 {
111 "name": "lighthouse-accessibility-score",
112 "label": "Lighthouse Accessibility Score",
113 "value": 76
114 },
115 {
116 "name": "lighthouse-performance-score",
117 "label": "Lighthouse Performance Score",
118 "value": 75
119 },
120 {
121 "name": "lighthouse-pwa-score",
122 "label": "Lighthouse Progressive Web App Score",
123 "value": 42
124 },
125 {
126 "name": "visually_complete_85",
127 "label": "85% Visually Complete",
128 "value": 1872
129 },
130 {
131 "name": "visually_complete",
132 "label": "Visually Complete",
133 "value": 9288
134 },
135 {
136 "name": "consistently-interactive",
137 "label": "Time to Interactive",
138 "value": 7408
139 },
140 {
141 "name": "first-interactive",
142 "label": "First CPU Idle",
143 "value": 7408
144 },
145 {
146 "name": "time-to-first-byte",
147 "label": "Time to First Byte",
148 "value": 402
149 },
150 {
151 "name": "speed_index",
152 "label": "Speed Index",
153 "value": 1822
154 },
155 {
156 "name": "first-meaningful-paint",
157 "label": "First Meaningful Paint",
158 "value": 1504
159 },
160 {
161 "name": "first-contentful-paint",
162 "label": "First Contentful Paint",
163 "value": 1504
164 },
165 {
166 "name": "firstRender",
167 "label": "First Paint",
168 "value": 1504
169 }
170 ],
171 "device": {
172 "title": "Motorola Moto G4"
173 },
174 "connection": {
175 "title": "Emerging Markets 3G"
176 },
177 "location": {
178 "name": "North Virginia, USA",
179 "emoji": "πŸ‡ΊπŸ‡Έ"
180 }
181}

Retrieve test artifacts

Required API Permission: Read Page Tests

For each Single Page Test, Calibre stores the following information:

  • lighthouse.json
  • render progress screenshots
  • MP4 video render
  • HAR file (Request log)
  • all other metrics and data available through the interface

You can obtain Single Page Test artifacts with the CLI and the Node.js API. When using the CLi, files will be saved to a test-artifacts directory. The Node.js API will return a list of URLs where the files can be downloaded.

1calibre test download-artifacts <uuid>
1#!/usr/bin/env node
2
3const { Test } = require('calibre')
4
5const getTestArtifactUrls = async () => {
6 // Required
7 const uuid = 'dfa1a00'
8
9 // Fetch the test results
10 const results = await Test.fetchArtifacts(uuid)
11
12 // Output the formatted JSON response
13 console.log(JSON.stringify(results, null, 2))
14}
15
16getTestArtifactUrls()
Example response
1βœ” Fetching test artifact URLs
2βœ” Screenshot
3βœ” MP4 Video Render
4βœ” HAR
5βœ” Lighthouse Report
6
7Saved artifacts to test-artifacts/dfa1a00
1{
2 "uuid": "dfa1a00",
3 "har": "https://calibre-screenshots-prod.s3.amazonaws.com/ef1ae88af9f4d643196a76cb62608449/b989bfe74fa26bed5063afb098e7ec4b.json.gz?X-Amz-Expires=3600&X-Amz-Date=20190725T061832Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAITFRYATLYAH7W3VQ/20190725/us-east-1/s3/aws4_request&X-Amz-SignedHeaders=host&X-Amz-Signature=71cfa944d9c8243a55149091efb88913ef99b7d3373f44f7c4f28a69b0a1279d",
4 "lighthouse": "https://calibre-screenshots-prod.s3.amazonaws.com/ef1ae88af9f4d643196a76cb62608449/f92ce9906f4a55728df1ff112246e079.json.gz?X-Amz-Expires=3600&X-Amz-Date=20190725T061832Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAITFRYATLYAH7W3VQ/20190725/us-east-1/s3/aws4_request&X-Amz-SignedHeaders=host&X-Amz-Signature=3cdb6e1fea6e00aa8c3e69d42b68aef0f1236550b858a8cc34bd7073275dd562",
5 "image": "https://calibre-screenshots-prod.s3.amazonaws.com/eb9dd012-7480-4368-b1f9-9e9f50e4f9f0/screenshot/screenshot.jpg",
6 "video": "https://calibre-screenshots-prod.s3.amazonaws.com/eb9dd012-7480-4368-b1f9-9e9f50e4f9f0/video-timeline/screencast.mp4"
7}

List all tests

Required API Permission: Read Page Tests
1calibre test list
1#!/usr/bin/env node
2
3const { Test } = require('calibre')
4
5const listAllTests = async () => {
6 // Fetch the test list
7 const tests = await Test.getList()
8
9 // Output the formatted JSON response
10 console.log(JSON.stringify(tests, null, 2))
11}
12
13listAllTests()
Example response
1UUID | URL | DEVICE | CONNECTION | LOCATION | STATUS
2dfa1a00 | calibreapp.com/ | Motorola Moto G4 | Not Throttled | πŸ‡ΊπŸ‡Έ North Virginia | Completed 4:11pm 25-Jul-2019
3efa99de | calibreapp.com/ | Motorola Moto G4 | Not Throttled | πŸ‡ΊπŸ‡Έ North Virginia | Completed 4:36pm 25-Jul-2019
1[
2 {
3 "uuid": "dfa1a00",
4 "url": "https://calibreapp.com",
5 "formattedTestUrl": "https://calibreapp.com/tests/dfa1a00/9f0cb96",
6 "adBlockerIsEnabled": false,
7 "device": {
8 "title": "Motorola Moto G4"
9 },
10 "connection": {
11 "title": "Emerging Markets 3G"
12 },
13 "location": {
14 "emoji": "πŸ‡ΊπŸ‡Έ",
15 "shortName": "North Virginia"
16 },
17 "status": "completed",
18 "updatedAt": "2019-07-25T06:11:09Z"
19 },
20 {
21 "uuid": "efa99de",
22 "url": "https://calibreapp.com",
23 "formattedTestUrl": "https://calibreapp.com/tests/efa99de/39d030e",
24 "adBlockerIsEnabled": false,
25 "device": {
26 "title": "Motorola Moto G4"
27 },
28 "connection": {
29 "title": "Emerging Markets 3G"
30 },
31 "location": {
32 "emoji": "πŸ‡ΊπŸ‡Έ",
33 "shortName": "North Virginia"
34 },
35 "status": "completed",
36 "updatedAt": "2019-07-25T06:36:18Z"
37 }
38]