diff options
Diffstat (limited to 'server/tests/api/videos')
-rw-r--r-- | server/tests/api/videos/multiple-servers.ts | 25 | ||||
-rw-r--r-- | server/tests/api/videos/single-server.ts | 4 | ||||
-rw-r--r-- | server/tests/api/videos/video-imports.ts | 10 | ||||
-rw-r--r-- | server/tests/api/videos/video-playlist-thumbnails.ts | 18 | ||||
-rw-r--r-- | server/tests/api/videos/video-playlists.ts | 16 | ||||
-rw-r--r-- | server/tests/api/videos/video-storyboard.ts | 6 |
6 files changed, 42 insertions, 37 deletions
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts index 27ba00d3d..e9aa0e3a1 100644 --- a/server/tests/api/videos/multiple-servers.ts +++ b/server/tests/api/videos/multiple-servers.ts | |||
@@ -9,7 +9,7 @@ import { | |||
9 | completeVideoCheck, | 9 | completeVideoCheck, |
10 | dateIsValid, | 10 | dateIsValid, |
11 | saveVideoInServers, | 11 | saveVideoInServers, |
12 | testImage | 12 | testImageGeneratedByFFmpeg |
13 | } from '@server/tests/shared' | 13 | } from '@server/tests/shared' |
14 | import { buildAbsoluteFixturePath, wait } from '@shared/core-utils' | 14 | import { buildAbsoluteFixturePath, wait } from '@shared/core-utils' |
15 | import { HttpStatusCode, VideoCommentThreadTree, VideoPrivacy } from '@shared/models' | 15 | import { HttpStatusCode, VideoCommentThreadTree, VideoPrivacy } from '@shared/models' |
@@ -70,8 +70,9 @@ describe('Test multiple servers', function () { | |||
70 | }) | 70 | }) |
71 | 71 | ||
72 | describe('Should upload the video and propagate on each server', function () { | 72 | describe('Should upload the video and propagate on each server', function () { |
73 | |||
73 | it('Should upload the video on server 1 and propagate on each server', async function () { | 74 | it('Should upload the video on server 1 and propagate on each server', async function () { |
74 | this.timeout(25000) | 75 | this.timeout(60000) |
75 | 76 | ||
76 | const attributes = { | 77 | const attributes = { |
77 | name: 'my super name for server 1', | 78 | name: 'my super name for server 1', |
@@ -175,8 +176,8 @@ describe('Test multiple servers', function () { | |||
175 | support: 'my super support text for server 2', | 176 | support: 'my super support text for server 2', |
176 | tags: [ 'tag1p2', 'tag2p2', 'tag3p2' ], | 177 | tags: [ 'tag1p2', 'tag2p2', 'tag3p2' ], |
177 | fixture: 'video_short2.webm', | 178 | fixture: 'video_short2.webm', |
178 | thumbnailfile: 'thumbnail.jpg', | 179 | thumbnailfile: 'custom-thumbnail.jpg', |
179 | previewfile: 'preview.jpg' | 180 | previewfile: 'custom-preview.jpg' |
180 | } | 181 | } |
181 | await servers[1].videos.upload({ token: userAccessToken, attributes, mode: 'resumable' }) | 182 | await servers[1].videos.upload({ token: userAccessToken, attributes, mode: 'resumable' }) |
182 | 183 | ||
@@ -229,8 +230,8 @@ describe('Test multiple servers', function () { | |||
229 | size: 750000 | 230 | size: 750000 |
230 | } | 231 | } |
231 | ], | 232 | ], |
232 | thumbnailfile: 'thumbnail', | 233 | thumbnailfile: 'custom-thumbnail', |
233 | previewfile: 'preview' | 234 | previewfile: 'custom-preview' |
234 | } | 235 | } |
235 | 236 | ||
236 | const { data } = await server.videos.list() | 237 | const { data } = await server.videos.list() |
@@ -619,9 +620,9 @@ describe('Test multiple servers', function () { | |||
619 | description: 'my super description updated', | 620 | description: 'my super description updated', |
620 | support: 'my super support text updated', | 621 | support: 'my super support text updated', |
621 | tags: [ 'tag_up_1', 'tag_up_2' ], | 622 | tags: [ 'tag_up_1', 'tag_up_2' ], |
622 | thumbnailfile: 'thumbnail.jpg', | 623 | thumbnailfile: 'custom-thumbnail.jpg', |
623 | originallyPublishedAt: '2019-02-11T13:38:14.449Z', | 624 | originallyPublishedAt: '2019-02-11T13:38:14.449Z', |
624 | previewfile: 'preview.jpg' | 625 | previewfile: 'custom-preview.jpg' |
625 | } | 626 | } |
626 | 627 | ||
627 | updatedAtMin = new Date() | 628 | updatedAtMin = new Date() |
@@ -674,8 +675,8 @@ describe('Test multiple servers', function () { | |||
674 | size: 292677 | 675 | size: 292677 |
675 | } | 676 | } |
676 | ], | 677 | ], |
677 | thumbnailfile: 'thumbnail', | 678 | thumbnailfile: 'custom-thumbnail', |
678 | previewfile: 'preview' | 679 | previewfile: 'custom-preview' |
679 | } | 680 | } |
680 | await completeVideoCheck({ server, originServer: servers[2], videoUUID: videoUpdated.uuid, attributes: checkAttributes }) | 681 | await completeVideoCheck({ server, originServer: servers[2], videoUUID: videoUpdated.uuid, attributes: checkAttributes }) |
681 | } | 682 | } |
@@ -685,7 +686,7 @@ describe('Test multiple servers', function () { | |||
685 | this.timeout(30000) | 686 | this.timeout(30000) |
686 | 687 | ||
687 | const attributes = { | 688 | const attributes = { |
688 | thumbnailfile: 'thumbnail.jpg' | 689 | thumbnailfile: 'custom-thumbnail.jpg' |
689 | } | 690 | } |
690 | 691 | ||
691 | updatedAtMin = new Date() | 692 | updatedAtMin = new Date() |
@@ -761,7 +762,7 @@ describe('Test multiple servers', function () { | |||
761 | for (const server of servers) { | 762 | for (const server of servers) { |
762 | const video = await server.videos.get({ id: videoUUID }) | 763 | const video = await server.videos.get({ id: videoUUID }) |
763 | 764 | ||
764 | await testImage(server.url, 'video_short1-preview.webm', video.previewPath) | 765 | await testImageGeneratedByFFmpeg(server.url, 'video_short1-preview.webm', video.previewPath) |
765 | } | 766 | } |
766 | }) | 767 | }) |
767 | }) | 768 | }) |
diff --git a/server/tests/api/videos/single-server.ts b/server/tests/api/videos/single-server.ts index 0cb64d5a5..66414aa5b 100644 --- a/server/tests/api/videos/single-server.ts +++ b/server/tests/api/videos/single-server.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | 1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ |
2 | 2 | ||
3 | import { expect } from 'chai' | 3 | import { expect } from 'chai' |
4 | import { checkVideoFilesWereRemoved, completeVideoCheck, testImage } from '@server/tests/shared' | 4 | import { checkVideoFilesWereRemoved, completeVideoCheck, testImageGeneratedByFFmpeg } from '@server/tests/shared' |
5 | import { wait } from '@shared/core-utils' | 5 | import { wait } from '@shared/core-utils' |
6 | import { Video, VideoPrivacy } from '@shared/models' | 6 | import { Video, VideoPrivacy } from '@shared/models' |
7 | import { | 7 | import { |
@@ -260,7 +260,7 @@ describe('Test a single server', function () { | |||
260 | 260 | ||
261 | for (const video of data) { | 261 | for (const video of data) { |
262 | const videoName = video.name.replace(' name', '') | 262 | const videoName = video.name.replace(' name', '') |
263 | await testImage(server.url, videoName, video.thumbnailPath) | 263 | await testImageGeneratedByFFmpeg(server.url, videoName, video.thumbnailPath) |
264 | } | 264 | } |
265 | }) | 265 | }) |
266 | 266 | ||
diff --git a/server/tests/api/videos/video-imports.ts b/server/tests/api/videos/video-imports.ts index 192b2aeb9..a684a55a0 100644 --- a/server/tests/api/videos/video-imports.ts +++ b/server/tests/api/videos/video-imports.ts | |||
@@ -3,7 +3,7 @@ | |||
3 | import { expect } from 'chai' | 3 | import { expect } from 'chai' |
4 | import { pathExists, readdir, remove } from 'fs-extra' | 4 | import { pathExists, readdir, remove } from 'fs-extra' |
5 | import { join } from 'path' | 5 | import { join } from 'path' |
6 | import { FIXTURE_URLS, testCaptionFile, testImage } from '@server/tests/shared' | 6 | import { FIXTURE_URLS, testCaptionFile, testImageGeneratedByFFmpeg } from '@server/tests/shared' |
7 | import { areHttpImportTestsDisabled } from '@shared/core-utils' | 7 | import { areHttpImportTestsDisabled } from '@shared/core-utils' |
8 | import { CustomConfig, HttpStatusCode, Video, VideoImportState, VideoPrivacy, VideoResolution, VideoState } from '@shared/models' | 8 | import { CustomConfig, HttpStatusCode, Video, VideoImportState, VideoPrivacy, VideoResolution, VideoState } from '@shared/models' |
9 | import { | 9 | import { |
@@ -67,7 +67,7 @@ async function checkVideoServer2 (server: PeerTubeServer, id: number | string) { | |||
67 | expect(video.description).to.equal('my super description') | 67 | expect(video.description).to.equal('my super description') |
68 | expect(video.tags).to.deep.equal([ 'supertag1', 'supertag2' ]) | 68 | expect(video.tags).to.deep.equal([ 'supertag1', 'supertag2' ]) |
69 | 69 | ||
70 | await testImage(server.url, 'thumbnail', video.thumbnailPath) | 70 | await testImageGeneratedByFFmpeg(server.url, 'custom-thumbnail', video.thumbnailPath) |
71 | 71 | ||
72 | expect(video.files).to.have.lengthOf(1) | 72 | expect(video.files).to.have.lengthOf(1) |
73 | 73 | ||
@@ -126,8 +126,8 @@ describe('Test video imports', function () { | |||
126 | ? '_yt_dlp' | 126 | ? '_yt_dlp' |
127 | : '' | 127 | : '' |
128 | 128 | ||
129 | await testImage(servers[0].url, 'video_import_thumbnail' + suffix, video.thumbnailPath) | 129 | await testImageGeneratedByFFmpeg(servers[0].url, 'video_import_thumbnail' + suffix, video.thumbnailPath) |
130 | await testImage(servers[0].url, 'video_import_preview' + suffix, video.previewPath) | 130 | await testImageGeneratedByFFmpeg(servers[0].url, 'video_import_preview' + suffix, video.previewPath) |
131 | } | 131 | } |
132 | 132 | ||
133 | const bodyCaptions = await servers[0].captions.list({ videoId: video.id }) | 133 | const bodyCaptions = await servers[0].captions.list({ videoId: video.id }) |
@@ -266,7 +266,7 @@ describe('Test video imports', function () { | |||
266 | name: 'my super name', | 266 | name: 'my super name', |
267 | description: 'my super description', | 267 | description: 'my super description', |
268 | tags: [ 'supertag1', 'supertag2' ], | 268 | tags: [ 'supertag1', 'supertag2' ], |
269 | thumbnailfile: 'thumbnail.jpg' | 269 | thumbnailfile: 'custom-thumbnail.jpg' |
270 | } | 270 | } |
271 | }) | 271 | }) |
272 | expect(video.name).to.equal('my super name') | 272 | expect(video.name).to.equal('my super name') |
diff --git a/server/tests/api/videos/video-playlist-thumbnails.ts b/server/tests/api/videos/video-playlist-thumbnails.ts index 356939b93..c274c20bf 100644 --- a/server/tests/api/videos/video-playlist-thumbnails.ts +++ b/server/tests/api/videos/video-playlist-thumbnails.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | 1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ |
2 | 2 | ||
3 | import { expect } from 'chai' | 3 | import { expect } from 'chai' |
4 | import { testImage } from '@server/tests/shared' | 4 | import { testImageGeneratedByFFmpeg } from '@server/tests/shared' |
5 | import { VideoPlaylistPrivacy } from '@shared/models' | 5 | import { VideoPlaylistPrivacy } from '@shared/models' |
6 | import { | 6 | import { |
7 | cleanupTests, | 7 | cleanupTests, |
@@ -83,7 +83,7 @@ describe('Playlist thumbnail', function () { | |||
83 | 83 | ||
84 | for (const server of servers) { | 84 | for (const server of servers) { |
85 | const p = await getPlaylistWithoutThumbnail(server) | 85 | const p = await getPlaylistWithoutThumbnail(server) |
86 | await testImage(server.url, 'thumbnail-playlist', p.thumbnailPath) | 86 | await testImageGeneratedByFFmpeg(server.url, 'thumbnail-playlist', p.thumbnailPath) |
87 | } | 87 | } |
88 | }) | 88 | }) |
89 | 89 | ||
@@ -95,7 +95,7 @@ describe('Playlist thumbnail', function () { | |||
95 | displayName: 'playlist with thumbnail', | 95 | displayName: 'playlist with thumbnail', |
96 | privacy: VideoPlaylistPrivacy.PUBLIC, | 96 | privacy: VideoPlaylistPrivacy.PUBLIC, |
97 | videoChannelId: servers[1].store.channel.id, | 97 | videoChannelId: servers[1].store.channel.id, |
98 | thumbnailfile: 'thumbnail.jpg' | 98 | thumbnailfile: 'custom-thumbnail.jpg' |
99 | } | 99 | } |
100 | }) | 100 | }) |
101 | playlistWithThumbnailId = created.id | 101 | playlistWithThumbnailId = created.id |
@@ -110,7 +110,7 @@ describe('Playlist thumbnail', function () { | |||
110 | 110 | ||
111 | for (const server of servers) { | 111 | for (const server of servers) { |
112 | const p = await getPlaylistWithThumbnail(server) | 112 | const p = await getPlaylistWithThumbnail(server) |
113 | await testImage(server.url, 'thumbnail', p.thumbnailPath) | 113 | await testImageGeneratedByFFmpeg(server.url, 'custom-thumbnail', p.thumbnailPath) |
114 | } | 114 | } |
115 | }) | 115 | }) |
116 | 116 | ||
@@ -135,7 +135,7 @@ describe('Playlist thumbnail', function () { | |||
135 | 135 | ||
136 | for (const server of servers) { | 136 | for (const server of servers) { |
137 | const p = await getPlaylistWithoutThumbnail(server) | 137 | const p = await getPlaylistWithoutThumbnail(server) |
138 | await testImage(server.url, 'thumbnail-playlist', p.thumbnailPath) | 138 | await testImageGeneratedByFFmpeg(server.url, 'thumbnail-playlist', p.thumbnailPath) |
139 | } | 139 | } |
140 | }) | 140 | }) |
141 | 141 | ||
@@ -160,7 +160,7 @@ describe('Playlist thumbnail', function () { | |||
160 | 160 | ||
161 | for (const server of servers) { | 161 | for (const server of servers) { |
162 | const p = await getPlaylistWithThumbnail(server) | 162 | const p = await getPlaylistWithThumbnail(server) |
163 | await testImage(server.url, 'thumbnail', p.thumbnailPath) | 163 | await testImageGeneratedByFFmpeg(server.url, 'custom-thumbnail', p.thumbnailPath) |
164 | } | 164 | } |
165 | }) | 165 | }) |
166 | 166 | ||
@@ -176,7 +176,7 @@ describe('Playlist thumbnail', function () { | |||
176 | 176 | ||
177 | for (const server of servers) { | 177 | for (const server of servers) { |
178 | const p = await getPlaylistWithoutThumbnail(server) | 178 | const p = await getPlaylistWithoutThumbnail(server) |
179 | await testImage(server.url, 'thumbnail-playlist', p.thumbnailPath) | 179 | await testImageGeneratedByFFmpeg(server.url, 'thumbnail-playlist', p.thumbnailPath) |
180 | } | 180 | } |
181 | }) | 181 | }) |
182 | 182 | ||
@@ -192,7 +192,7 @@ describe('Playlist thumbnail', function () { | |||
192 | 192 | ||
193 | for (const server of servers) { | 193 | for (const server of servers) { |
194 | const p = await getPlaylistWithThumbnail(server) | 194 | const p = await getPlaylistWithThumbnail(server) |
195 | await testImage(server.url, 'thumbnail', p.thumbnailPath) | 195 | await testImageGeneratedByFFmpeg(server.url, 'custom-thumbnail', p.thumbnailPath) |
196 | } | 196 | } |
197 | }) | 197 | }) |
198 | 198 | ||
@@ -224,7 +224,7 @@ describe('Playlist thumbnail', function () { | |||
224 | 224 | ||
225 | for (const server of servers) { | 225 | for (const server of servers) { |
226 | const p = await getPlaylistWithThumbnail(server) | 226 | const p = await getPlaylistWithThumbnail(server) |
227 | await testImage(server.url, 'thumbnail', p.thumbnailPath) | 227 | await testImageGeneratedByFFmpeg(server.url, 'custom-thumbnail', p.thumbnailPath) |
228 | } | 228 | } |
229 | }) | 229 | }) |
230 | 230 | ||
diff --git a/server/tests/api/videos/video-playlists.ts b/server/tests/api/videos/video-playlists.ts index 9277b49f4..3bfa874cb 100644 --- a/server/tests/api/videos/video-playlists.ts +++ b/server/tests/api/videos/video-playlists.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | 1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ |
2 | 2 | ||
3 | import { expect } from 'chai' | 3 | import { expect } from 'chai' |
4 | import { checkPlaylistFilesWereRemoved, testImage } from '@server/tests/shared' | 4 | import { checkPlaylistFilesWereRemoved, testImageGeneratedByFFmpeg } from '@server/tests/shared' |
5 | import { wait } from '@shared/core-utils' | 5 | import { wait } from '@shared/core-utils' |
6 | import { uuidToShort } from '@shared/extra-utils' | 6 | import { uuidToShort } from '@shared/extra-utils' |
7 | import { | 7 | import { |
@@ -133,7 +133,7 @@ describe('Test video playlists', function () { | |||
133 | displayName: 'my super playlist', | 133 | displayName: 'my super playlist', |
134 | privacy: VideoPlaylistPrivacy.PUBLIC, | 134 | privacy: VideoPlaylistPrivacy.PUBLIC, |
135 | description: 'my super description', | 135 | description: 'my super description', |
136 | thumbnailfile: 'thumbnail.jpg', | 136 | thumbnailfile: 'custom-thumbnail.jpg', |
137 | videoChannelId: servers[0].store.channel.id | 137 | videoChannelId: servers[0].store.channel.id |
138 | } | 138 | } |
139 | }) | 139 | }) |
@@ -225,7 +225,7 @@ describe('Test video playlists', function () { | |||
225 | displayName: 'my super playlist', | 225 | displayName: 'my super playlist', |
226 | privacy: VideoPlaylistPrivacy.PUBLIC, | 226 | privacy: VideoPlaylistPrivacy.PUBLIC, |
227 | description: 'my super description', | 227 | description: 'my super description', |
228 | thumbnailfile: 'thumbnail.jpg', | 228 | thumbnailfile: 'custom-thumbnail.jpg', |
229 | videoChannelId: servers[0].store.channel.id | 229 | videoChannelId: servers[0].store.channel.id |
230 | } | 230 | } |
231 | }) | 231 | }) |
@@ -286,7 +286,7 @@ describe('Test video playlists', function () { | |||
286 | attributes: { | 286 | attributes: { |
287 | displayName: 'playlist 3', | 287 | displayName: 'playlist 3', |
288 | privacy: VideoPlaylistPrivacy.PUBLIC, | 288 | privacy: VideoPlaylistPrivacy.PUBLIC, |
289 | thumbnailfile: 'thumbnail.jpg', | 289 | thumbnailfile: 'custom-thumbnail.jpg', |
290 | videoChannelId: servers[1].store.channel.id | 290 | videoChannelId: servers[1].store.channel.id |
291 | } | 291 | } |
292 | }) | 292 | }) |
@@ -314,11 +314,11 @@ describe('Test video playlists', function () { | |||
314 | 314 | ||
315 | const playlist2 = body.data.find(p => p.displayName === 'playlist 2') | 315 | const playlist2 = body.data.find(p => p.displayName === 'playlist 2') |
316 | expect(playlist2).to.not.be.undefined | 316 | expect(playlist2).to.not.be.undefined |
317 | await testImage(server.url, 'thumbnail-playlist', playlist2.thumbnailPath) | 317 | await testImageGeneratedByFFmpeg(server.url, 'thumbnail-playlist', playlist2.thumbnailPath) |
318 | 318 | ||
319 | const playlist3 = body.data.find(p => p.displayName === 'playlist 3') | 319 | const playlist3 = body.data.find(p => p.displayName === 'playlist 3') |
320 | expect(playlist3).to.not.be.undefined | 320 | expect(playlist3).to.not.be.undefined |
321 | await testImage(server.url, 'thumbnail', playlist3.thumbnailPath) | 321 | await testImageGeneratedByFFmpeg(server.url, 'custom-thumbnail', playlist3.thumbnailPath) |
322 | } | 322 | } |
323 | 323 | ||
324 | const body = await servers[2].playlists.list({ start: 0, count: 5 }) | 324 | const body = await servers[2].playlists.list({ start: 0, count: 5 }) |
@@ -336,7 +336,7 @@ describe('Test video playlists', function () { | |||
336 | 336 | ||
337 | const playlist2 = body.data.find(p => p.displayName === 'playlist 2') | 337 | const playlist2 = body.data.find(p => p.displayName === 'playlist 2') |
338 | expect(playlist2).to.not.be.undefined | 338 | expect(playlist2).to.not.be.undefined |
339 | await testImage(servers[2].url, 'thumbnail-playlist', playlist2.thumbnailPath) | 339 | await testImageGeneratedByFFmpeg(servers[2].url, 'thumbnail-playlist', playlist2.thumbnailPath) |
340 | 340 | ||
341 | expect(body.data.find(p => p.displayName === 'playlist 3')).to.not.be.undefined | 341 | expect(body.data.find(p => p.displayName === 'playlist 3')).to.not.be.undefined |
342 | }) | 342 | }) |
@@ -502,7 +502,7 @@ describe('Test video playlists', function () { | |||
502 | displayName: 'playlist 3 updated', | 502 | displayName: 'playlist 3 updated', |
503 | description: 'description updated', | 503 | description: 'description updated', |
504 | privacy: VideoPlaylistPrivacy.UNLISTED, | 504 | privacy: VideoPlaylistPrivacy.UNLISTED, |
505 | thumbnailfile: 'thumbnail.jpg', | 505 | thumbnailfile: 'custom-thumbnail.jpg', |
506 | videoChannelId: servers[1].store.channel.id | 506 | videoChannelId: servers[1].store.channel.id |
507 | }, | 507 | }, |
508 | playlistId: playlistServer2Id2 | 508 | playlistId: playlistServer2Id2 |
diff --git a/server/tests/api/videos/video-storyboard.ts b/server/tests/api/videos/video-storyboard.ts index 5fde6ce45..fc4b4450f 100644 --- a/server/tests/api/videos/video-storyboard.ts +++ b/server/tests/api/videos/video-storyboard.ts | |||
@@ -110,7 +110,11 @@ describe('Test video storyboard', function () { | |||
110 | await waitJobs(servers) | 110 | await waitJobs(servers) |
111 | 111 | ||
112 | for (const server of servers) { | 112 | for (const server of servers) { |
113 | await checkStoryboard({ server, uuid, tilesCount: 6, minSize: 250 }) | 113 | try { |
114 | await checkStoryboard({ server, uuid, tilesCount: 6, minSize: 250 }) | ||
115 | } catch { // FIXME: to remove after ffmpeg CI upgrade, ffmpeg CI version (4.3) generates a 7.6s length video | ||
116 | await checkStoryboard({ server, uuid, tilesCount: 8, minSize: 250 }) | ||
117 | } | ||
114 | } | 118 | } |
115 | }) | 119 | }) |
116 | 120 | ||