sandwich-slack 0.1.2.0 → 0.2.0.0
raw patch · 7 files changed
+31/−31 lines, 7 filesdep +unliftiodep +unliftio-coredep −safe-exceptionsPVP ok
version bump matches the API change (PVP)
Dependencies added: unliftio, unliftio-core
Dependencies removed: safe-exceptions
API changes (from Hackage documentation)
Files
- CHANGELOG.md +4/−1
- LICENSE +1/−1
- app/Main.hs +2/−12
- sandwich-slack.cabal +10/−7
- src/Test/Sandwich/Formatters/Slack.hs +11/−5
- src/Test/Sandwich/Formatters/Slack/Internal/Markdown.hs +2/−4
- src/Test/Sandwich/Formatters/Slack/Internal/ProgressBar.hs +1/−1
CHANGELOG.md view
@@ -1,6 +1,9 @@ # Changelog for sandwich-slack -## Unreleased changes+## 0.2.0.0++* BREAKING CHANGE: switch most monads away from using `MonadBaseControl IO` and switch to `MonadUnliftIO`.+* Windows support improvements. ## 0.1.2.0
LICENSE view
@@ -1,4 +1,4 @@-Copyright Tom McLaughlin (c) 2023+Copyright Tom McLaughlin (c) 2025 All rights reserved.
app/Main.hs view
@@ -5,15 +5,11 @@ import Control.Concurrent import Control.Monad.IO.Class-import Data.Time import GHC.Stack import Test.Sandwich import Test.Sandwich.Formatters.Print import Test.Sandwich.Formatters.Slack--#ifndef mingw32_HOST_OS import Test.Sandwich.Formatters.TerminalUI-#endif simple :: TopSpec@@ -42,18 +38,12 @@ , slackFormatterVisibilityThreshold = Just 50 } -#ifndef mingw32_HOST_OS-baseFormatter = SomeFormatter defaultTerminalUIFormatter-#else-baseFormatter = SomeFormatter defaultPrintFormatter-#endif- main :: IO () main = runSandwich options simple where options = defaultOptions {- optionsTestArtifactsDirectory = TestArtifactsGeneratedDirectory "test_runs" (show <$> getCurrentTime)- , optionsFormatters = [baseFormatter, SomeFormatter slackFormatter]+ optionsTestArtifactsDirectory = defaultTestArtifactsDirectory+ , optionsFormatters = [SomeFormatter defaultTerminalUIFormatter, SomeFormatter slackFormatter] } -- * Util
sandwich-slack.cabal view
@@ -1,13 +1,13 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.35.2.+-- This file has been generated from package.yaml by hpack version 0.37.0. -- -- see: https://github.com/sol/hpack ----- hash: 6138f55d728f79ee3b7afe065d16ee37a3b075445596cb82a236df8f0e23bf47+-- hash: 29f4c739f9e4b5cb58a9ff1224cbc09f9740944e94f09355caa1d660ff54d8bb name: sandwich-slack-version: 0.1.2.0+version: 0.2.0.0 synopsis: Sandwich integration with Slack description: Please see the <https://codedownio.github.io/sandwich/docs/extensions/sandwich-slack documentation>. category: Testing@@ -15,7 +15,7 @@ bug-reports: https://github.com/codedownio/sandwich/issues author: Tom McLaughlin maintainer: tom@codedown.io-copyright: 2023 Tom McLaughlin+copyright: 2025 Tom McLaughlin license: BSD3 license-file: LICENSE build-type: Simple@@ -60,12 +60,13 @@ , monad-logger , mtl , safe- , safe-exceptions , sandwich , stm , string-interpolate , text , time+ , unliftio+ , unliftio-core , vector , wreq default-language: Haskell2010@@ -98,13 +99,14 @@ , monad-logger , mtl , safe- , safe-exceptions , sandwich , sandwich-slack , stm , string-interpolate , text , time+ , unliftio+ , unliftio-core , vector , wreq default-language: Haskell2010@@ -138,12 +140,13 @@ , monad-logger , mtl , safe- , safe-exceptions , sandwich , stm , string-interpolate , text , time+ , unliftio+ , unliftio-core , vector , wreq default-language: Haskell2010
src/Test/Sandwich/Formatters/Slack.hs view
@@ -30,9 +30,9 @@ import Control.Applicative import Control.Concurrent import Control.Concurrent.STM-import Control.Exception.Safe import Control.Monad import Control.Monad.IO.Class+import Control.Monad.IO.Unlift import Control.Monad.Logger hiding (logError) import qualified Data.Aeson as A import Data.Foldable@@ -50,6 +50,7 @@ import Test.Sandwich.Formatters.Slack.Internal.ProgressBar import Test.Sandwich.Formatters.Slack.Internal.Types import Test.Sandwich.Internal+import UnliftIO.Exception data SlackFormatter = SlackFormatter {@@ -121,7 +122,7 @@ , slackFormatterMaxMessageSize = optSlackMaxMessageSize <|> slackFormatterMaxMessageSize } -runApp :: (MonadIO m, MonadCatch m, MonadLogger m) => SlackFormatter -> [RunNode BaseContext] -> BaseContext -> m ()+runApp :: (MonadUnliftIO m, MonadLogger m) => SlackFormatter -> [RunNode BaseContext] -> BaseContext -> m () runApp sf@(SlackFormatter {..}) rts _bc = do startTime <- liftIO getCurrentTime @@ -159,12 +160,13 @@ loop +publishTree :: SlackFormatter -> M.Map Int (T.Text, Int) -> NominalDiffTime -> [RunNodeWithStatus context Status l t] -> ProgressBarInfo publishTree sf idToLabelAndVisibilityThreshold elapsed tree = pbi where pbi = ProgressBarInfo { progressBarInfoTopMessage = T.pack <$> (slackFormatterTopMessage sf) , progressBarInfoBottomMessage = Just fullBottomMessage- , progressBarInfoSize = Just (100.0 * (fromIntegral (succeeded + pending + failed) / (fromIntegral total)))+ , progressBarInfoSize = Just (100.0 * (fromIntegral (succeeded + pending' + failed) / (fromIntegral total))) , progressBarInfoAttachments = Nothing , progressBarInfoBlocks = Just $ case slackFormatterMaxFailures sf of Nothing -> mconcat blocks@@ -179,7 +181,7 @@ fullBottomMessage = case runningMessage of Nothing -> bottomMessage Just t -> T.pack t <> "\n" <> bottomMessage- bottomMessage = [i|#{succeeded} succeeded, #{failed} failed, #{pending} pending, #{totalRunningTests} running of #{total} (#{formatNominalDiffTime elapsed} elapsed)|]+ bottomMessage = [i|#{succeeded} succeeded, #{failed} failed, #{pending'} pending, #{totalRunningTests} running of #{total} (#{formatNominalDiffTime elapsed} elapsed)|] blocks = catMaybes $ flip concatMap tree $ extractValuesControlRecurse $ \case -- Recurse into grouping nodes, because their failures are actually just derived from child failures@@ -192,12 +194,13 @@ total = countWhere isItBlock tree succeeded = countWhere isSuccessItBlock tree- pending = countWhere isPendingItBlock tree+ pending' = countWhere isPendingItBlock tree failed = countWhere isFailedItBlock tree totalRunningTests = countWhere isRunningItBlock tree -- totalNotStartedTests = countWhere isNotStartedItBlock tree +singleFailureBlocks :: SlackFormatter -> M.Map Int (T.Text, Int) -> RunNodeWithStatus context s l t -> FailureReason -> [A.Value] singleFailureBlocks sf idToLabelAndVisibilityThreshold node reason = catMaybes [ Just $ markdownSectionWithLines [":red_circle: *" <> label <> "*"] @@ -235,10 +238,13 @@ _ -> Just l label = T.intercalate ", " $ mapMaybe filterFn $ toList $ runTreeAncestors $ runNodeCommon node +extraFailuresBlock :: Int -> A.Value extraFailuresBlock numExtraFailures = markdownSectionWithLines [[i|+ #{numExtraFailures} more failure|]] +markdownBlockWithLines :: [T.Text] -> A.Value markdownBlockWithLines ls = A.object [("type", A.String "mrkdwn"), ("text", A.String $ T.unlines ls)] +markdownSectionWithLines :: [T.Text] -> A.Value markdownSectionWithLines ls = A.object [("type", A.String "section"), ("text", markdownBlockWithLines ls)] addToLastLine :: [T.Text] -> T.Text -> [T.Text]
src/Test/Sandwich/Formatters/Slack/Internal/Markdown.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} module Test.Sandwich.Formatters.Slack.Internal.Markdown where @@ -13,16 +12,14 @@ toMarkdown :: FailureReason -> T.Text toMarkdown (Reason {..}) = T.pack failureReason-#ifndef mingw32_HOST_OS toMarkdown (RawImage {..}) = T.pack failureFallback-#endif toMarkdown (ChildrenFailed {failureNumChildren=n}) = [i|#{n} #{if n == 1 then ("child" :: T.Text) else "children"} failed|] toMarkdown (ExpectedButGot {..}) = [i|Expected *#{failureValue1}* but got *#{failureValue2}*|] toMarkdown (DidNotExpectButGot {..}) = [i|Did not expect *#{failureValue1}*|] toMarkdown (GotException {..}) = case failureMessage of Just msg -> [i|Got exception (_#{msg}_): #{failureException}|] Nothing -> [i|Got exception (no message): #{failureException}|]-toMarkdown (Pending {..}) = "Example was pending"+toMarkdown (Pending {}) = "Example was pending" toMarkdown (GetContextException {..}) = [i|Context exception: #{failureException}|] toMarkdown (GotAsyncException {..}) = case failureMessage of Just msg -> [i|Got async exception (_#{msg}_): #{failureAsyncException}|]@@ -33,6 +30,7 @@ callStackToMarkdown (SlackFormatterTopNCallStackFrames n) cs = "\n\n" <> showCallStack (fromCallSiteList $ L.take n $ getCallStack cs) callStackToMarkdown SlackFormatterFullCallStack cs = "\n\n" <> showCallStack cs +showCallStack :: CallStack -> T.Text showCallStack (getCallStack -> rows) = ["> *" <> (T.pack name) <> "*, called at " <> [i|_#{srcLocPackage}_:*#{srcLocFile}*:#{srcLocStartLine}:#{srcLocStartCol}|] | (name, SrcLoc {..}) <- rows]
src/Test/Sandwich/Formatters/Slack/Internal/ProgressBar.hs view
@@ -79,5 +79,5 @@ lightBlocks = round $ (100 - n) * multiplier multiplier = 0.5 - roundTo :: (Fractional a, RealFrac a) => Integer -> a -> a+ roundTo :: (RealFrac a) => Integer -> a -> a roundTo places num = (fromInteger $ round $ num * (10^places)) / (10.0^^places)