github.com/ChicK00o/awgo@v0.29.4/workflow_test.go (about)

     1  // Copyright (c) 2018 Dean Jackson <deanishe@deanishe.net>
     2  // MIT Licence - http://opensource.org/licenses/MIT
     3  
     4  package aw
     5  
     6  import (
     7  	"encoding/json"
     8  	"errors"
     9  	"fmt"
    10  
    11  	"log"
    12  	"os"
    13  	"strings"
    14  	"testing"
    15  
    16  	"github.com/stretchr/testify/assert"
    17  	"github.com/stretchr/testify/require"
    18  	"go.deanishe.net/env"
    19  
    20  	"github.com/ChicK00o/awgo/util"
    21  )
    22  
    23  // TestWorkflowValues tests workflow name, bundle ID etc.
    24  func TestWorkflowValues(t *testing.T) {
    25  	t.Parallel()
    26  
    27  	withTestWf(func(wf *Workflow) {
    28  		assert.Equal(t, tName, wf.Name(), "unexpected name")
    29  		assert.Equal(t, tBundleID, wf.BundleID(), "unexpected bundle ID")
    30  	})
    31  }
    32  
    33  // TestInvalidEnv executes workflow in an invalid environment.
    34  func TestInvalidEnv(t *testing.T) {
    35  	assert.Panics(t, func() { NewFromEnv(env.MapEnv{}) })
    36  }
    37  
    38  // Options correctly alter Workflow.
    39  func TestNew(t *testing.T) {
    40  	t.Parallel()
    41  
    42  	tests := []struct {
    43  		opt  Option                  // option to set
    44  		test func(wf *Workflow) bool // function to verify change was made
    45  		desc string                  // test title
    46  	}{
    47  		{
    48  			HelpURL("http://www.example.com"),
    49  			func(wf *Workflow) bool { return wf.helpURL == "http://www.example.com" },
    50  			"Set HelpURL"},
    51  		{
    52  			MaxResults(10),
    53  			func(wf *Workflow) bool { return wf.maxResults == 10 },
    54  			"Set MaxResults"},
    55  		{
    56  			LogPrefix("blah"),
    57  			func(wf *Workflow) bool { return wf.logPrefix == "blah" },
    58  			"Set LogPrefix"},
    59  		{
    60  			SessionName("SESH"),
    61  			func(wf *Workflow) bool { return wf.sessionName == "SESH" },
    62  			"Set SessionName"},
    63  		{
    64  			SortOptions(),
    65  			func(wf *Workflow) bool { return wf.sortOptions == nil },
    66  			"Set SortOptions"},
    67  		{
    68  			SuppressUIDs(true),
    69  			func(wf *Workflow) bool { return wf.Feedback.NoUIDs == true },
    70  			"Set SuppressUIDs"},
    71  		{
    72  			MagicPrefix("aw:"),
    73  			func(wf *Workflow) bool { return wf.magicPrefix == "aw:" },
    74  			"Set MagicPrefix"},
    75  		{
    76  			MaxLogSize(2048),
    77  			func(wf *Workflow) bool { return wf.maxLogSize == 2048 },
    78  			"Set MaxLogSize"},
    79  		{
    80  			TextErrors(true),
    81  			func(wf *Workflow) bool { return wf.textErrors == true },
    82  			"Set TextErrors"},
    83  		{
    84  			AddMagic(&mockMA{}),
    85  			func(wf *Workflow) bool { return wf.magicActions.actions["test"] != nil },
    86  			"Add Magic"},
    87  		{
    88  			RemoveMagic(logMA{}),
    89  			func(wf *Workflow) bool { return wf.magicActions.actions["log"] == nil },
    90  			"Remove Magic"},
    91  	}
    92  
    93  	for _, td := range tests {
    94  		td := td // capture variable
    95  		t.Run(fmt.Sprintf("Option(%#v)", td.opt), func(t *testing.T) {
    96  			t.Parallel()
    97  			wf := New(td.opt)
    98  			assert.True(t, td.test(wf), "option failed")
    99  		})
   100  	}
   101  }
   102  
   103  func TestWorkflow_Run(t *testing.T) {
   104  	withTestWf(func(wf *Workflow) {
   105  		var called bool
   106  
   107  		run := func() { called = true }
   108  		wf.Run(run)
   109  
   110  		assert.True(t, called, "run wasn't called")
   111  	})
   112  }
   113  
   114  func TestWorkflow_Run_Rescue(t *testing.T) {
   115  	withTestWf(func(wf *Workflow) {
   116  		me := &mockExit{}
   117  		exitFunc = me.Exit
   118  		defer func() { exitFunc = os.Exit }()
   119  		wf.Run(func() { panic("aaaargh!") })
   120  		assert.Equal(t, 1, me.code, "workflow did not catch panic")
   121  	})
   122  }
   123  
   124  // TestWorkflowDir verifies that AwGo finds the right directory.
   125  func TestWorkflow_Dir(t *testing.T) {
   126  	t.Parallel()
   127  
   128  	var (
   129  		cwd string
   130  		err error
   131  	)
   132  
   133  	cwd, err = os.Getwd()
   134  	require.Nil(t, err, "Getwd failed")
   135  
   136  	tests := []struct {
   137  		in, x string
   138  	}{
   139  		{"testdata", "testdata"},
   140  		{"testdata/subdir", "testdata"},
   141  		{".", "."},
   142  		{"", ""},
   143  	}
   144  
   145  	for _, td := range tests {
   146  		td := td
   147  		t.Run(fmt.Sprintf("findWorkflowRoot(%q)", td.in), func(t *testing.T) {
   148  			t.Parallel()
   149  			assert.Equal(t, td.x, findWorkflowRoot(td.in), "unexpected root")
   150  		})
   151  	}
   152  
   153  	wf := New()
   154  	assert.Equal(t, cwd, wf.Dir(), "unexpected workflow dir")
   155  }
   156  
   157  // Check that AW's directories exist
   158  func TestWorkflow_awDirs(t *testing.T) {
   159  	t.Parallel()
   160  
   161  	withTestWf(func(wf *Workflow) {
   162  		p := wf.awCacheDir()
   163  		assert.True(t, util.PathExists(p), "AW cache dir does not exist")
   164  		assert.True(t, strings.HasSuffix(p, "_aw"), "AW cache is not called '_aw'")
   165  
   166  		p = wf.awDataDir()
   167  		assert.True(t, util.PathExists(p), "AW data dir does not exist")
   168  		assert.True(t, strings.HasSuffix(p, "_aw"), "AW data is not called '_aw'")
   169  	})
   170  }
   171  
   172  // Check log is rotated
   173  func TestWorkflow_logRotate(t *testing.T) {
   174  	logInitialized = false // ensure log is created
   175  	withTestWf(func(wf *Workflow) {
   176  		wf.Configure(MaxLogSize(10))
   177  		log.Print("more than 10 bytes")
   178  
   179  		assert.True(t, util.PathExists(wf.LogFile()), "log file does not exist")
   180  
   181  		logInitialized = false // ensure log is created
   182  		wf.initializeLogging()
   183  		assert.True(t, util.PathExists(wf.LogFile()+".1"), "log file not rotated")
   184  	})
   185  }
   186  
   187  // Variables are correctly set
   188  func TestWorkflow_Vars(t *testing.T) {
   189  	t.Parallel()
   190  
   191  	vars := map[string]string{
   192  		"key1": "val1",
   193  		"key2": "val2",
   194  		"key3": "val3",
   195  		"key4": "val4",
   196  		"key5": "val5",
   197  	}
   198  
   199  	withTestWf(func(wf *Workflow) {
   200  		for k, v := range vars {
   201  			wf.Var(k, v)
   202  		}
   203  		assert.Equal(t, vars, wf.Vars(), "Unexpected Vars")
   204  	})
   205  }
   206  
   207  func TestWorkflow_Rerun(t *testing.T) {
   208  	t.Parallel()
   209  
   210  	withTestWf(func(wf *Workflow) {
   211  		v := 0.1
   212  		wf.Rerun(v)
   213  		assert.Equal(t, v, wf.Feedback.rerun, "Unexpected Rerun")
   214  	})
   215  }
   216  
   217  func TestWorkflow_Fatal(t *testing.T) {
   218  	var exit bool
   219  	exitFunc = func(code int) { exit = true }
   220  	withTestWf(func(wf *Workflow) {
   221  		wf.Fatal("")
   222  		assert.True(t, exit, "Fatal did not exit")
   223  	})
   224  
   225  	exit = false
   226  	withTestWf(func(wf *Workflow) {
   227  		wf.FatalError(errors.New("some error"))
   228  		assert.True(t, exit, "FatalError did not exit")
   229  	})
   230  
   231  	exit = false
   232  	withTestWf(func(wf *Workflow) {
   233  		wf.Fatalf("die")
   234  		assert.True(t, exit, "Fatalf did not exit")
   235  	})
   236  }
   237  
   238  func TestRunCommand(t *testing.T) {
   239  	t.Parallel()
   240  
   241  	err := runCommand("/usr/bin/true")
   242  	assert.Nil(t, err, `call "/usr/bin/true" failed`)
   243  	err = runCommand("/does/not/exist")
   244  	assert.NotNil(t, err, `call to "/does/not/exist" returned no error`)
   245  }
   246  
   247  // New initialises a Workflow with the default settings. Name,
   248  // bundle ID, version etc. are read from the environment variables set by Alfred.
   249  func ExampleNew() {
   250  	wf := New()
   251  	// Name is read from environment
   252  	fmt.Println(wf.Name())
   253  	// BundleID is read from environment
   254  	fmt.Println(wf.BundleID())
   255  	// Version is from info.plist
   256  	fmt.Println(wf.Version())
   257  	// Output:
   258  	// AwGo
   259  	// net.deanishe.awgo
   260  	// 1.2.0
   261  }
   262  
   263  // Pass one or more Options to New() to configure the created Workflow.
   264  func ExampleNew_withOptions() {
   265  	wf := New(HelpURL("http://www.example.com"), MaxResults(200))
   266  	fmt.Println(wf.helpURL)
   267  	fmt.Println(wf.maxResults)
   268  	// Output:
   269  	// http://www.example.com
   270  	// 200
   271  }
   272  
   273  // The normal way to create a new Item, but not the normal way to use it.
   274  //
   275  // Typically, when you're done adding Items, you call SendFeedback() to
   276  // send the results to Alfred.
   277  func ExampleWorkflow_NewItem() {
   278  	wf := New()
   279  	// Create a new item via the Workflow object, which will
   280  	// track the Item and send it to Alfred when you call
   281  	// Workflow.SendFeedback()
   282  	//
   283  	// Title is the only required value.
   284  	it := wf.NewItem("First Result").
   285  		Subtitle("Some details here")
   286  
   287  	// Just to see what it looks like...
   288  	data, _ := json.Marshal(it)
   289  	fmt.Println(string(data))
   290  	// Output: {"title":"First Result","subtitle":"Some details here","valid":false}
   291  }
   292  
   293  // Change Workflow's configuration after creation, then revert it.
   294  func ExampleWorkflow_Configure() {
   295  	wf := New()
   296  	// Default settings (false and 0)
   297  	fmt.Println(wf.textErrors)
   298  	fmt.Println(wf.maxResults)
   299  	// Turn text errors on, set max results and save Option to revert
   300  	// to previous configuration
   301  	previous := wf.Configure(TextErrors(true), MaxResults(200))
   302  	fmt.Println(wf.textErrors)
   303  	fmt.Println(wf.maxResults)
   304  	// Revert to previous configuration
   305  	wf.Configure(previous)
   306  	fmt.Println(wf.textErrors)
   307  	fmt.Println(wf.maxResults)
   308  	// Output:
   309  	// false
   310  	// 0
   311  	// true
   312  	// 200
   313  	// false
   314  	// 0
   315  }
   316  
   317  func ExampleWorkflow_Warn() {
   318  	wf := New()
   319  	// Add some items
   320  	wf.NewItem("Item One").
   321  		Subtitle("Subtitle one")
   322  	wf.NewItem("Item Two").
   323  		Subtitle("Subtitle two")
   324  
   325  	// Delete existing items, add a warning, then
   326  	// immediately send feedback
   327  	wf.Warn("Bad Items", "Those items are boring")
   328  
   329  	// Output:
   330  	// {
   331  	//   "variables": {
   332  	//     "AW_SESSION_ID": "test-session-id"
   333  	//   },
   334  	//   "items": [
   335  	//     {
   336  	//       "title": "Bad Items",
   337  	//       "subtitle": "Those items are boring",
   338  	//       "valid": false,
   339  	//       "icon": {
   340  	//         "path": "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/AlertCautionBadgeIcon.icns"
   341  	//       }
   342  	//     }
   343  	//   ]
   344  	// }
   345  }
   346  
   347  func ExampleArgVars() {
   348  	// Set workflow variables from Alfred's Run Script Action
   349  	av := NewArgVars()
   350  	av.Arg("baz")        // Set output (i.e. next action's {query}) to "baz"
   351  	av.Var("foo", "bar") // Set workflow variable "foo" to "bar"
   352  	if err := av.Send(); err != nil {
   353  		panic(err)
   354  	}
   355  	// Output: {"alfredworkflow":{"arg":"baz","variables":{"foo":"bar"}}}
   356  }