Filedownload mit Puppeteer in Docker
Für manche Testszenarien muss auch ein Dateidownload mit getestet werden, z.B. um die resultierende Datei auf Korrektheit zu prüfen. Für Ende-zu-Ende Tests gibt es diverse Werkzeuge, eins davon ist das von Google entwickelte Puppeteer. Mit Puppeteer lässt sich aktuell der Chrome Browser fernsteuern, eine Erweiterung auf Mozilla Firefox ist ebenfalls in Arbeit.
In diesem Beitrag wird gezeigt, wie mit Docker und Puppeteer ein entsprechendes Testszenario umgesetzt werden kann.
Zunächst wird ein passendes Docker Image benötigt. Darin sollte Puppeteer und ein passender Chrome installiert sein. Als Basis Image wird daher das trion/ng-cli-karma Image verwendet, dass speziell für Angular entwickelt wurde.
Dockerfile
um Puppeteer als Docker Image bereitzustellenFROM trion/ng-cli-karma
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true NODE_PATH=/usr/local/lib/node_modules
RUN npm install -g puppeteer
CMD node run.js
Da bereits ein Chrome installiert ist, wird Puppeteer angewiesen, keinen erneuten Download vorzunehmen.
Das Image kann dann mit docker build
gebaut werden, wichtig ist dass das Dockerfile
im selben Ordner liegt.
$ docker build -t puppeteer .
Sending build context to Docker daemon 3.584kB
Step 1/3 : FROM trion/ng-cli-karma
---> 94372ad9d5d1
Step 2/3 : ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
---> Running in feab2e67e622
Removing intermediate container feab2e67e622
---> 354e0de9a8ab
Step 3/3 : RUN npm i -g puppeteer
---> Running in 5340333268a8
> puppeteer@1.19.0 install /usr/local/lib/node_modules/puppeteer
> node install.js
+ puppeteer@1.19.0
added 43 packages from 22 contributors in 3.981s
Removing intermediate container 5340333268a8
---> c432bc9716c3
Successfully built c432bc9716c3
Successfully tagged puppeteer:latest
Nun wird noch eine Steuerung für Puppeteer benötigt. Dazu wird ein kurzes JavaScript Programm geschrieben, dass dann mit der node Runtime im Docker ausgeführt werden kann.
Das Docker Image ist bereits so konfiguriert, dass es die Datei run.js
erwartet und ausführt.
run.js
const puppeteer = require('puppeteer');
puppeteer.launch({headless: false, executablePath: "/usr/bin/chromium-browser"})
.then(async browser => {
const page = await browser.newPage();
await page.goto('https://my.example.com');
//warten auf geladene seite, falls moeglich, sonst mit wartezeit arbeiten
// await page.waitForNavigation({ waitUntil: 'networkidle2' });
await page.waitFor(4000);
await page._client.send('Page.setDownloadBehavior', {
behavior: 'allow',
downloadPath: './'
});
//z.b. fuer diagnose
//await page.screenshot({path: 'screenshot.png'});
await page.click('button[title="Export CSV"]');
await page.waitFor(20000); // Downloadzeit fuer die Datei
await browser.close();
});
Der Docker Aufruf ist relativ simpel:
Es wird lediglich ein einzelner Aufruf durchgeführt, daher soll der Docker Container mit Puppeteer anschließend abgeräumt werden: --rm
Außerdem muss das aktuelle Verzeichnis, in dem sich das Puppeteer Programm als run.js
befindet, im Container verfügbar gemacht werden.
In diesem Verzeichnis wird auch der Download angelegt: --volume
Damit die angelegten Dateien nicht root gehören (dem User, als der der Docker Daemon läuft) sollte zusätzlich die ID des aktuellen Users im Container gesetzt werden: -u $(id -u)
Schließlich muss der Name des Containerimage auch angegeben werden, wir hatten das Image beim Bauen als puppeteer
getaggt.
$ docker run --rm --volume $PWD:/app -u $(id -u) puppeteer
Im aktuellen Verzeichnis befindet sich anschließend die mit Puppeteer heruntergeladene Datei und ggf. erzeugte Screenshots.
Zu den Themen Docker, Webentwicklung, React und Angular bieten wir sowohl Beratung, Entwicklungsunterstützung als auch passende Schulungen an:
Auch für Ihren individuellen Bedarf können wir Workshops und Schulungen anbieten. Sprechen Sie uns gerne an.