Skip to content

Commit

Permalink
First version of sydtest-webdriver, sydtest-webdriver-yesod and sydte…
Browse files Browse the repository at this point in the history
…st-webdriver-screenshot
  • Loading branch information
Tom Sydney Kerckhove committed Apr 19, 2022
1 parent 9265dba commit aac96e2
Show file tree
Hide file tree
Showing 31 changed files with 1,023 additions and 3 deletions.
46 changes: 46 additions & 0 deletions nix/fonts-conf.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{ lib
, stdenv
, libxslt
, fontconfig
, lndir
, roboto
, twitter-color-emoji
}:

# Chromium reads FONTCONFIG_SYSROOT, and uses that instead of / for all font-related filepaths
# Chromium also reads FONTCONFIG_PATH, but always also reads FONTCONFIG_SYSROOT/etc/fonts/font.conf so you cannot override fonts, only add to them
# so here we have to nix build of something that looks like / with everything font-related, (which I could only do based on the strace output showing me which things it tries to read in FONTCONFIG_SYSROOT)
# and then set FONTCONFIG_SYSROOT to that.
# and I only found FONTCONFIG_SYSROOT by looking through the chromium source code
let
fonts = {
"roboto" = roboto;
"twitter" = twitter-color-emoji;
};
fontNames = builtins.attrNames fonts;
in
stdenv.mkDerivation {
name = "fonts-config";
unpackPhase = "true";
nativeBuildInputs = [ libxslt lndir ];
buildInputs = [ fontconfig ];
inherit fontNames;
installPhase =
let singleDir = name: fontPkg: ''
echo ${fontPkg}
ln -s ${fontPkg} $out/etc/fonts/${name}
'';
in
''
mkdir -p $out/etc/fonts
${lib.concatStringsSep "\n" (lib.mapAttrsToList singleDir fonts)}
mkdir -p $out/fonts
xsltproc \
--stringparam fontNames "$fontNames" \
--path ${fontconfig.out}/share/xml/fontconfig \
${./fonts.xsl} ${fontconfig.out}/etc/fonts/fonts.conf \
> $out/etc/fonts/fonts.conf
'';
}
30 changes: 30 additions & 0 deletions nix/fonts.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0"?>

<!--
This is an adaptation of https://github.com/NixOS/nixpkgs/blob/068984c00e0d4e54b6684d98f6ac47c92dcb642e/pkgs/development/libraries/fontconfig/make-fonts-conf.xsl
-->

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="str"
>


<xsl:param name="fontNames" />

<xsl:template match="/fontconfig">

<fontconfig>
<cachedir prefix="xdg">fontconfig</cachedir>


<xsl:for-each select="str:tokenize($fontNames)">
<dir>/etc/fonts/<xsl:value-of select="." />/share/fonts</dir>
<xsl:text>&#0010;</xsl:text>
</xsl:for-each>
</fontconfig>

</xsl:template>

</xsl:stylesheet>
30 changes: 30 additions & 0 deletions nix/overlay.nix
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,36 @@ with final.haskell.lib;
unset NIX_REDIRECTS LD_PRELOAD
'';
});
"sydtest-webdriver" = overrideCabal (sydtestPkg "sydtest-webdriver") (old: {
testDepends = (old.testDepends or [ ]) ++ (with final; [
chromedriver
chromium
selenium-server-standalone
]);
preConfigure = (old.preConfigure or "") + ''
export FONTCONFIG_SYSROOT=${final.callPackage ./fonts-conf.nix {}}
'';
});
"sydtest-webdriver-screenshot" = overrideCabal (sydtestPkg "sydtest-webdriver-screenshot") (old: {
testDepends = (old.testDepends or [ ]) ++ (with final; [
chromedriver
chromium
selenium-server-standalone
]);
preConfigure = (old.preConfigure or "") + ''
export FONTCONFIG_SYSROOT=${final.callPackage ./fonts-conf.nix {}}
'';
});
"sydtest-webdriver-yesod" = overrideCabal (sydtestPkg "sydtest-webdriver-yesod") (old: {
testDepends = (old.testDepends or [ ]) ++ (with final; [
chromedriver
chromium
selenium-server-standalone
]);
preConfigure = (old.preConfigure or "") + ''
export FONTCONFIG_SYSROOT=${final.callPackage ./fonts-conf.nix {}}
'';
});
"sydtest-misbehaved-test-suite" = sydtestPkg "sydtest-misbehaved-test-suite";
};

Expand Down
5 changes: 5 additions & 0 deletions shell.nix
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
let
pkgs = import ./nix/pkgs.nix { };
pre-commit = import ./nix/pre-commit.nix;
fontconfigDir = pkgs.callPackage ./nix/fonts-conf.nix { };
in
pkgs.haskell.lib.buildStackProject {
name = "sydtest-shell";
buildInputs = with pkgs; [
chromedriver
chromium
coreutils
mongodb
niv
postgresql
rabbitmq-server
redis
selenium-server-standalone
zlib
] ++ pre-commit.tools;
shellHook = ''
export TMPDIR=/tmp
${pre-commit.check.shellHook}
export FONTCONFIG_SYSROOT=${fontconfigDir}
'';
}
4 changes: 4 additions & 0 deletions stack.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@ packages:
- sydtest-servant
- sydtest-typed-process
- sydtest-wai
- sydtest-webdriver
- sydtest-webdriver-screenshot
- sydtest-webdriver-yesod
- sydtest-yesod

- sydtest-misbehaved-test-suite

extra-deps:
- envparse-0.4.1@sha256:989902e6368532548f61de1fa245ad2b39176cddd8743b20071af519a709ce30,2842
- github: NorfairKing/safe-coloured-text
Expand Down
2 changes: 1 addition & 1 deletion sydtest-wai/sydtest-wai.cabal
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cabal-version: 1.12

-- This file has been generated from package.yaml by hpack version 0.34.4.
-- This file has been generated from package.yaml by hpack version 0.34.6.
--
-- see: https://github.com/sol/hpack

Expand Down
1 change: 1 addition & 0 deletions sydtest-webdriver-screenshot/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
screenshot-comparison
5 changes: 5 additions & 0 deletions sydtest-webdriver-screenshot/LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Sydtest License

Copyright (c) 2022 Tom Sydney Kerckhove

See the Sydtest License at https://github.com/NorfairKing/sydtest/blob/master/sydtest/LICENSE.md for the full license text.
48 changes: 48 additions & 0 deletions sydtest-webdriver-screenshot/package.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: sydtest-webdriver-screenshot
version: 0.0.0.0
license: OtherLicense
license-file: LICENSE.md
author: "Tom Sydney Kerckhove"
maintainer: "[email protected]"
copyright: "Copyright (c) 2022 Tom Sydney Kerckhove"
category: Testing
synopsis: A webdriver screenshot companion library for sydtest

extra-source-files:
- LICENSE.md

dependencies:
- base >= 4.7 && < 5

library:
source-dirs: src
dependencies:
- JuicyPixels
- bytestring
- http-types
- mtl
- network-uri
- path
- path-io
- sydtest
- sydtest-wai
- sydtest-webdriver
- webdriver

tests:
sydtest-webdriver-screenshot-test:
main: Spec.hs
source-dirs: test
build-tools: sydtest-discover
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
dependencies:
- http-types
- network-uri
- sydtest
- sydtest-wai
- sydtest-webdriver
- sydtest-webdriver-screenshot
- wai
90 changes: 90 additions & 0 deletions sydtest-webdriver-screenshot/src/Test/Syd/Webdriver/Screenshot.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
-- Because of webdriver using dangerous constructors
{-# OPTIONS_GHC -fno-warn-incomplete-record-updates #-}
-- For the undefined trick
{-# OPTIONS_GHC -fno-warn-unused-pattern-binds #-}

module Test.Syd.Webdriver.Screenshot where

import Codec.Picture as Picture
import Control.Monad.Reader
import qualified Data.ByteString as SB
import qualified Data.ByteString.Lazy as LB
import Path
import Path.IO
import System.Exit
import Test.Syd
import Test.Syd.Webdriver
import Test.WebDriver as WD

-- | A screenshot with location
data Screenshot = Screenshot
{ -- | File location for comparisons
screenshotFile :: !(Path Abs File),
-- | Decoded image
screenshotImage :: !(Picture.Image PixelRGB8)
}

-- | Take a screenshot and turn it into a golden test.
goldenScreenshotHere :: FilePath -> WebdriverTestM app (GoldenTest Screenshot)
goldenScreenshotHere fp = pureGoldenScreenshot fp <$> WD.screenshot

-- | Make a golden test for a given screenshot in lazy 'LB.ByteString' form.
pureGoldenScreenshot :: FilePath -> LB.ByteString -> GoldenTest Screenshot
pureGoldenScreenshot fp contents =
GoldenTest
{ goldenTestRead = do
relFile <- parseRelFile fp
currentDir <- getCurrentDir
let resolvedFile = currentDir </> relFile
mContents <- forgivingAbsence $ SB.readFile $ fromAbsFile resolvedFile
forM mContents $ \cts -> do
case decodePng cts of
Left err -> die err
Right dynamicImage ->
pure $
Screenshot
{ screenshotFile = resolvedFile,
screenshotImage = convertRGB8 dynamicImage
},
goldenTestProduce = do
let sb = LB.toStrict contents
case decodePng sb of
Left err -> expectationFailure $ "Could not parse screenshot as png: " <> err
Right dynamicImage -> do
let image = convertRGB8 dynamicImage
relFile <- parseRelFile fp
tempDir <- resolveDir' "screenshot-comparison"
let tempFile = tempDir </> relFile
ensureDir $ parent tempFile
-- Write it to a file so we can compare it if it differs.
writePng (fromAbsFile tempFile) image
pure $
Screenshot
{ screenshotFile = tempFile,
screenshotImage = image
},
goldenTestWrite = \(Screenshot _ actual) -> do
relFile <- parseRelFile fp
currentDir <- getCurrentDir
let resolvedFile = currentDir </> relFile
ensureDir $ parent resolvedFile
writePng (fromAbsFile resolvedFile) actual,
goldenTestCompare = \(Screenshot actualPath actual) (Screenshot expectedPath expected) ->
if actual == expected
then Nothing
else
Just $
ExpectationFailed $
unlines
[ "Screenshots differ.",
"expected: " <> fromAbsFile expectedPath,
"actual: " <> fromAbsFile actualPath
]
}
63 changes: 63 additions & 0 deletions sydtest-webdriver-screenshot/sydtest-webdriver-screenshot.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
cabal-version: 1.12

-- This file has been generated from package.yaml by hpack version 0.34.6.
--
-- see: https://github.com/sol/hpack

name: sydtest-webdriver-screenshot
version: 0.0.0.0
synopsis: A webdriver screenshot companion library for sydtest
category: Testing
author: Tom Sydney Kerckhove
maintainer: [email protected]
copyright: Copyright (c) 2022 Tom Sydney Kerckhove
license: OtherLicense
license-file: LICENSE.md
build-type: Simple
extra-source-files:
LICENSE.md

library
exposed-modules:
Test.Syd.Webdriver.Screenshot
other-modules:
Paths_sydtest_webdriver_screenshot
hs-source-dirs:
src
build-depends:
JuicyPixels
, base >=4.7 && <5
, bytestring
, http-types
, mtl
, network-uri
, path
, path-io
, sydtest
, sydtest-wai
, sydtest-webdriver
, webdriver
default-language: Haskell2010

test-suite sydtest-webdriver-screenshot-test
type: exitcode-stdio-1.0
main-is: Spec.hs
other-modules:
Test.Syd.Webdriver.Screenshot.App
Test.Syd.Webdriver.ScreenshotSpec
Paths_sydtest_webdriver_screenshot
hs-source-dirs:
test
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-tool-depends:
sydtest-discover:sydtest-discover
build-depends:
base >=4.7 && <5
, http-types
, network-uri
, sydtest
, sydtest-wai
, sydtest-webdriver
, sydtest-webdriver-screenshot
, wai
default-language: Haskell2010
1 change: 1 addition & 0 deletions sydtest-webdriver-screenshot/test/Spec.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{-# OPTIONS_GHC -F -pgmF sydtest-discover #-}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{-# LANGUAGE OverloadedStrings #-}

module Test.Syd.Webdriver.Screenshot.App where

import Network.HTTP.Types as HTTP
import Network.Wai as Wai

exampleApplication :: Wai.Application
exampleApplication req sendResp =
sendResp $
responseLBS
HTTP.ok200
(requestHeaders req)
"<html><body><h1>Hello World</h1><h2>Foo</h2><h3>Bar</h3><h4>Quux</h4></body></html>"
Loading

0 comments on commit aac96e2

Please sign in to comment.