Skip to content

Commit

Permalink
ci: use docker for puppeteer screenshots
Browse files Browse the repository at this point in the history
  • Loading branch information
ifiokjr committed Jul 18, 2019
1 parent a5a659a commit 68dbf2d
Show file tree
Hide file tree
Showing 31 changed files with 225 additions and 22 deletions.
1 change: 1 addition & 0 deletions .dockerignore
@@ -0,0 +1 @@
node_modules
2 changes: 0 additions & 2 deletions @remirror/renderer-react/src/__tests__/serializer.spec.tsx
Expand Up @@ -33,7 +33,6 @@ test('ReactSerializer.fromExtensionManager', () => {
describe('ReactSerializer', () => {
describe('#serializeNode', () => {
it('serializes the node', () => {
// TODO add marks to the jest-remirror library
const node = PMNode.fromJSON(schema, simpleJSON);
expect(shallow(serializer.serializeNode(node) as JSX.Element)).toMatchElement(
<p>
Expand Down Expand Up @@ -62,7 +61,6 @@ describe('ReactSerializer', () => {
});

it('serializes the node with nested data', () => {
// TODO add marks to the jest-remirror library
const node = PMNode.fromJSON(schema, testJSON);
expect(shallow(serializer.serializeNode(node) as JSX.Element)).toMatchElement(
<p>
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions e2e/__image_snapshots__/chromium-wysiwyg-editor-dom-snap.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions e2e/__image_snapshots__/chromium-wysiwyg-editor-ssr-snap.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 5 additions & 2 deletions e2e/twitter.puppeteer.ts
Expand Up @@ -16,9 +16,8 @@ describe('Twitter Editor Snapshots', () => {
const ssrIdentifier = prefixBrowserName('twitter-editor-ssr');
const domIdentifier = prefixBrowserName('twitter-editor-dom');

beforeEach(async () => {
beforeAll(async () => {
url = getUrl('twitter', 'next');
await jestPuppeteer.resetPage();
});

describeServer(['next'])('SSR', () => {
Expand Down Expand Up @@ -63,6 +62,10 @@ describe('Twitter Editor Snapshots', () => {
});

describe.each(URLDescriptor.twitter)('%s: Twitter Showcase', (_, path) => {
beforeAll(async () => {
await jestPuppeteer.resetPage();
});

beforeEach(async () => {
await page.goto(path);
});
Expand Down
3 changes: 1 addition & 2 deletions e2e/wysiwyg.puppeteer.ts
Expand Up @@ -8,9 +8,8 @@ describe('Wysiwyg Editor Snapshots', () => {
const ssrIdentifier = prefixBrowserName('wysiwyg-editor-ssr');
const domIdentifier = prefixBrowserName('wysiwyg-editor-dom');

beforeEach(async () => {
beforeAll(async () => {
url = getUrl('wysiwyg', 'next');
await jestPuppeteer.resetPage();
});

describeServer(['next'])('SSR', () => {
Expand Down
5 changes: 4 additions & 1 deletion package.json
Expand Up @@ -62,8 +62,11 @@
"storybook:test": "start-storybook -p 3002 -c support/storybook --quiet --ci",
"test": "jest --verbose",
"test:e2e": "run-s test:puppeteer test:puppeteer:firefox",
"test:e2e:docker": "docker-compose -f ./support/docker/docker-compose.yml run puppeteer-linux",
"docker:puppeteer:linux": "docker-compose -f ./support/docker/docker-compose.yml build puppeteer-linux",
"docker:puppeteer:windows": "docker-compose -f ./support/docker/docker-compose.yml build puppeteer-windows",
"test:puppeteer": "jest --verbose --runInBand --config e2e/jest.config.js",
"test:puppeteer:debug": "cross-env PUPPETEER_DEBUG=true yarn test:puppeteer",
"test:puppeteer:debug": "cross-env PUPPETEER_SERVERS=storybook PUPPETEER_DEBUG=true yarn test:puppeteer",
"test:puppeteer:firefox": "cross-env PUPPETEER_BROWSER=firefox yarn test:puppeteer",
"test:puppeteer:storybook": "cross-env PUPPETEER_SERVERS=storybook yarn test:puppeteer",
"test:watch": "jest --watch --verbose=false --coverage=false",
Expand Down
29 changes: 29 additions & 0 deletions support/docker/docker-compose.yml
@@ -0,0 +1,29 @@
version: '3.7'
services:
puppeteer-linux:
environment:
PUPPETEER_DOCKER: 'true'
build:
dockerfile: ./support/docker/puppeteer-linux-dev.Dockerfile
context: ../../
volumes:
- type: bind
source: ../../e2e
target: /remirror/e2e
volume:
nocopy: false
command: 'yarn test:puppeteer'

puppeteer-windows:
environment:
PUPPETEER_DOCKER: 'true'
build:
dockerfile: ./support/docker/puppeteer-windows.Dockerfile
context: ../../
volumes:
- type: bind
source: ../../e2e
target: /remirror/e2e
volume:
nocopy: false
command: 'yarn test:puppeteer'
7 changes: 7 additions & 0 deletions support/docker/puppeteer-linux-dev.Dockerfile
@@ -0,0 +1,7 @@
FROM remirror/puppeteer-linux:0.0.2

RUN mkdir /remirror
WORKDIR /remirror
COPY ./package.json yarn.lock ./
COPY . .
RUN yarn
28 changes: 28 additions & 0 deletions support/docker/puppeteer-linux.Dockerfile
@@ -0,0 +1,28 @@
FROM node:10.16.0-slim

RUN apt-get update \
&& apt-get install -y --no-install-recommends apt-utils \
&& apt-get -y install xvfb gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 \
libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 \
libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 \
libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 \
libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils \
&& apt-get install -y wget --no-install-recommends \
&& wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
&& sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
&& apt-get update -qqy \
&& apt-get install -y google-chrome-unstable --no-install-recommends \
&& rm -rf /var/lib/apt/lists/*

# Install puppeteer so it's available in the container.
RUN yarn add puppeteer && yarn add puppeteer-firefox

# Add user so we don't need --no-sandbox.
# RUN groupadd -r pptruser && useradd -r -g pptruser -G audio,video pptruser \
# && mkdir -p /home/pptruser/Downloads /app \
# && chown -R pptruser:pptruser /home/pptruser \
# && chown -R pptruser:pptruser /node_modules \
# && chown -R pptruser:pptruser /app

# Run everything after as non-privileged user.
# USER pptruser
77 changes: 77 additions & 0 deletions support/docker/puppeteer-windows.Dockerfile
@@ -0,0 +1,77 @@
# This is still a work in progress.
# Taken from https://github.com/StefanScherer/dockerfiles-windows/blob/master/node/10/Dockerfile
# See https://github.com/StefanScherer/windows-docker-machine for runninfg from mac

ARG core=mcr.microsoft.com/windows/servercore:ltsc2019
ARG target=mcr.microsoft.com/windows/servercore:ltsc2019
FROM $core as download

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

ENV GPG_VERSION 2.3.4

RUN Invoke-WebRequest $('https://files.gpg4win.org/gpg4win-vanilla-{0}.exe' -f $env:GPG_VERSION) -OutFile 'gpg4win.exe' -UseBasicParsing ; \
Start-Process .\gpg4win.exe -ArgumentList '/S' -NoNewWindow -Wait

RUN @( \
'94AE36675C464D64BAFA68DD7434390BDBE9B9C5', \
'FD3A5288F042B6850C66B31F09FE44734EB7990E', \
'71DCFD284A79C3B38668286BC97EC7A07EDE3FC1', \
'DD8F2338BAE7501E3DD5AC78C273792F7D83545D', \
'C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8', \
'B9AE9905FFD7803F25714661B63B535A4C206CA9', \
'77984A986EBC2AA786BC0F66B01FBB92821C587A', \
'8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600', \
'4ED778F539E3634C779C87C6D7062848A1AB005C', \
'A48C2BEE680E841632CD4E44F07496B3EB3C1762', \
'B9E2F5981AA6E0CD28160D9FF13993A75599653C' \
) | foreach { \
gpg --keyserver ha.pool.sks-keyservers.net --recv-keys $_ ; \
}

ENV NODE_VERSION 10.16.0

RUN Invoke-WebRequest $('https://nodejs.org/dist/v{0}/SHASUMS256.txt.asc' -f $env:NODE_VERSION) -OutFile 'SHASUMS256.txt.asc' -UseBasicParsing ; \
gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc

RUN Invoke-WebRequest $('https://nodejs.org/dist/v{0}/node-v{0}-win-x64.zip' -f $env:NODE_VERSION) -OutFile 'node.zip' -UseBasicParsing ; \
$sum = $(cat SHASUMS256.txt.asc | sls $(' node-v{0}-win-x64.zip' -f $env:NODE_VERSION)) -Split ' ' ; \
if ((Get-FileHash node.zip -Algorithm sha256).Hash -ne $sum[0]) { Write-Error 'SHA256 mismatch' } ; \
Expand-Archive node.zip -DestinationPath C:\ ; \
Rename-Item -Path $('C:\node-v{0}-win-x64' -f $env:NODE_VERSION) -NewName 'C:\nodejs'

ENV YARN_VERSION 1.16.0

RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ; \
Invoke-WebRequest $('https://yarnpkg.com/downloads/{0}/yarn-{0}.msi' -f $env:YARN_VERSION) -OutFile yarn.msi -UseBasicParsing ; \
$sig = Get-AuthenticodeSignature yarn.msi ; \
if ($sig.Status -ne 'Valid') { Write-Error 'Authenticode signature is not valid' } ; \
Write-Output $sig.SignerCertificate.Thumbprint ; \
if (@( \
'7E253367F8A102A91D04829E37F3410F14B68A5F', \
'AF764E1EA56C762617BDC757C8B0F3780A0CF5F9' \
) -notcontains $sig.SignerCertificate.Thumbprint) { Write-Error 'Unknown signer certificate' } ; \
Start-Process msiexec.exe -ArgumentList '/i', 'yarn.msi', '/quiet', '/norestart' -NoNewWindow -Wait

ENV GIT_VERSION 2.22.0
ENV GIT_DOWNLOAD_URL https://github.com/git-for-windows/git/releases/download/v${GIT_VERSION}.windows.1/MinGit-${GIT_VERSION}-busybox-64-bit.zip
ENV GIT_SHA256 9817ab455d9cbd0b09d8664b4afbe4bbf78d18b556b3541d09238501a749486c

RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ; \
Invoke-WebRequest -UseBasicParsing $env:GIT_DOWNLOAD_URL -OutFile git.zip; \
if ((Get-FileHash git.zip -Algorithm sha256).Hash -ne $env:GIT_SHA256) {exit 1} ; \
Expand-Archive git.zip -DestinationPath C:\git; \
Remove-Item git.zip

FROM $target

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

ENV NPM_CONFIG_LOGLEVEL info

COPY --from=download /nodejs /nodejs
COPY --from=download [ "/Program Files (x86)/yarn", "/yarn" ]
COPY --from=download /git /git

RUN $env:PATH = 'C:\nodejs;C:\yarn\bin;C:\git\cmd;C:\git\mingw64\bin;C:\git\usr\bin;{0}' -f $env:PATH ; \
[Environment]::SetEnvironmentVariable('PATH', $env:PATH, [EnvironmentVariableTarget]::Machine)
2 changes: 1 addition & 1 deletion support/fixtures/test-urls.ts
Expand Up @@ -41,7 +41,7 @@ export const getBrowserName = (): BrowserName => process.env.PUPPETEER_BROWSER |
/**
* Prefix the browser name to the passed in string
*/
export const prefixBrowserName = (value: string) => `${getBrowserName()}-${value}`;
export const prefixBrowserName = (value: string) => `${getBrowserName()}-${process.platform}-${value}`;

/**
* Declare the globals used throughout tests
Expand Down
4 changes: 3 additions & 1 deletion support/jest/jest.framework.ts
Expand Up @@ -2,6 +2,8 @@ import 'jest-extended';

import { configureToMatchImageSnapshot } from 'jest-image-snapshot';

const { CI } = process.env;

if (__E2E__) {
jest.setTimeout(120000);
jest.retryTimes(2);
Expand All @@ -10,7 +12,7 @@ if (__E2E__) {
const customConfig = { threshold: 0.3 };
const toMatchImageSnapshot = configureToMatchImageSnapshot({
customDiffConfig: customConfig,
failureThreshold: 1000,
failureThreshold: CI ? 4000 : 1000,
failureThresholdType: 'pixel',
});

Expand Down
6 changes: 3 additions & 3 deletions support/jest/puppeteer.ts
Expand Up @@ -15,19 +15,19 @@ const serverConfig: Record<SupportedServers, JestDevServerOptions> = {
command: `yarn storybook:${CI ? 'ci' : 'test'}`,
port: 3002,
usedPortAction: 'kill',
launchTimeout: 60000,
launchTimeout: 120000,
},
next: {
command: 'yarn next:ci',
port: 3001,
usedPortAction: 'kill',
launchTimeout: 60000,
launchTimeout: 120000,
},
docz: {
command: 'yarn dev:docs',
port: 3000,
usedPortAction: 'kill',
launchTimeout: 60000,
launchTimeout: 120000,
},
};

Expand Down
20 changes: 14 additions & 6 deletions support/pipelines/jobs.yml
Expand Up @@ -10,13 +10,13 @@ jobs:
steps:
- template: yarn-install.yml
- bash: yarn integrity
displayName: 'Dependency integrity'
displayName: 'Check yarn lock file is up to date'
- bash: yarn ci:audit
displayName: 'Security audit'
displayName: 'Check for security audit flags in dependencies'
- bash: yarn lint
displayName: 'Linter'
displayName: 'Check all lint rules'
- bash: yarn typecheck
displayName: 'Typecheck'
displayName: 'Typecheck code and tests'

- ${{ if eq(parameters.name, 'Linux') }}:
- job: ${{ parameters.name }}UnitTests
Expand All @@ -26,7 +26,7 @@ jobs:
- template: yarn-install.yml
- bash: |
yarn test
displayName: 'Run unit tests'
displayName: 'Run unit tests across project'
- ${{ if eq(parameters.name, 'Linux') }}:
- job: ${{ parameters.name }}SizeChecks
Expand All @@ -37,7 +37,7 @@ jobs:
- bash: yarn build
displayName: 'Build project'
- bash: yarn size
displayName: 'Size limit check'
displayName: 'Check size limits'

- job: ${{ parameters.name }}IntegrationTests
pool:
Expand All @@ -54,8 +54,16 @@ jobs:

- bash: yarn test:puppeteer
displayName: 'Run integration tests on chrome'
env:
CI: 'true'

# Firefox tests are currently failing because image snapshots aren't consistent on linux
# Use a docker image to generate snapshots so that they can run across environments
- bash: yarn test:puppeteer:firefox || true
displayName: 'Run integration tests on firefox'
env:
CI: 'true'

- publish: $(System.DefaultWorkingDirectory)/e2e/__image_snapshots__
condition: always()
artifact: ImageSnapshots

0 comments on commit 68dbf2d

Please sign in to comment.