-
Notifications
You must be signed in to change notification settings - Fork 73
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🐹 feat(triggers): Playwright Engine (#3922)
* feat(triggers): Playwright Engine * cleanup * updating dependency name * adding playwright install * adding playwright install
- Loading branch information
Showing
15 changed files
with
1,566 additions
and
681 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
package trigger | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"path/filepath" | ||
) | ||
|
||
var ( | ||
node = "node" | ||
app = "npx" | ||
libName = "@tracetest/playwright-engine" | ||
scriptPath = "script.js" | ||
) | ||
|
||
func PLAYWRIGHTENGINE() Triggerer { | ||
return &playwrightTriggerer{} | ||
} | ||
|
||
type playwrightTriggerer struct{} | ||
|
||
func (te *playwrightTriggerer) Trigger(ctx context.Context, triggerConfig Trigger, opts *Options) (Response, error) { | ||
response := Response{ | ||
Result: TriggerResult{ | ||
Type: te.Type(), | ||
PlaywrightEngine: &PlaywrightEngineResponse{ | ||
Success: false, | ||
}, | ||
}, | ||
} | ||
|
||
err := validate() | ||
if err != nil { | ||
return response, err | ||
} | ||
|
||
err = os.WriteFile(scriptPath, []byte(triggerConfig.PlaywrightEngine.Script), 0644) | ||
if err != nil { | ||
return response, err | ||
} | ||
|
||
err = start(opts.TraceID.String(), opts.SpanID.String(), triggerConfig.PlaywrightEngine.Target, triggerConfig.PlaywrightEngine.Method) | ||
if err != nil { | ||
os.Remove(scriptPath) | ||
return response, err | ||
} | ||
|
||
os.Remove(scriptPath) | ||
response.Result.PlaywrightEngine.Success = true | ||
return response, err | ||
} | ||
|
||
func (t *playwrightTriggerer) Type() TriggerType { | ||
return TriggerTypePlaywrightEngine | ||
} | ||
|
||
const TriggerTypePlaywrightEngine TriggerType = "playwrightengine" | ||
|
||
func validate() error { | ||
_, err := exec.LookPath(node) | ||
if err != nil { | ||
return fmt.Errorf("node not found in PATH") | ||
} | ||
|
||
_, err = exec.LookPath(app) | ||
if err != nil { | ||
return fmt.Errorf("npm not found in PATH") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func start(traceId, spanId, url, method string) error { | ||
wd, err := os.Getwd() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
res, err := execCommand( | ||
app, | ||
"playwright", | ||
"install", | ||
) | ||
|
||
if err != nil { | ||
return fmt.Errorf("error installing playwright: %s, %w", res, err) | ||
} | ||
|
||
path, err := filepath.Abs(fmt.Sprintf("%s/%s", wd, scriptPath)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
res, err = execCommand( | ||
app, | ||
libName, | ||
"--scriptPath", | ||
path, | ||
"--traceId", | ||
traceId, | ||
"--spanId", | ||
spanId, | ||
"--url", | ||
url, | ||
"--method", | ||
method) | ||
|
||
if err != nil { | ||
return fmt.Errorf("error executing playwright engine: %s, %w", res, err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func execCommand(name string, args ...string) (string, error) { | ||
cmd := exec.Command(name, args...) | ||
|
||
var out bytes.Buffer | ||
var stderr bytes.Buffer | ||
cmd.Stdout = &out | ||
cmd.Stderr = &stderr | ||
err := cmd.Run() | ||
|
||
if err != nil { | ||
return fmt.Sprint(err) + ": " + stderr.String(), err | ||
} | ||
|
||
return out.String(), nil | ||
} | ||
|
||
type PlaywrightEngineRequest struct { | ||
Target string `json:"target,omitempty"` | ||
Script string `json:"script,omitempty"` | ||
Method string `json:"method,omitempty"` | ||
} | ||
|
||
type PlaywrightEngineResponse struct { | ||
Success bool `json:"success"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package trigger_test | ||
|
||
import ( | ||
"net/http" | ||
"net/http/httptest" | ||
"testing" | ||
|
||
"github.com/kubeshop/tracetest/agent/workers/trigger" | ||
triggerer "github.com/kubeshop/tracetest/agent/workers/trigger" | ||
"github.com/kubeshop/tracetest/server/pkg/id" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func createOptions() *trigger.Options { | ||
return &trigger.Options{ | ||
TraceID: id.NewRandGenerator().TraceID(), | ||
SpanID: id.NewRandGenerator().SpanID(), | ||
} | ||
} | ||
|
||
var script = ` | ||
const { expect } = require('@playwright/test'); | ||
async function basicTest(page) { | ||
await expect(page.getByText('OK')).toBeVisible(); | ||
} | ||
module.exports = { basicTest }; | ||
` | ||
|
||
func TestTrigger(t *testing.T) { | ||
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { | ||
|
||
assert.Equal(t, "GET", req.Method) | ||
|
||
rw.WriteHeader(200) | ||
_, err := rw.Write([]byte(`OK`)) | ||
assert.NoError(t, err) | ||
})) | ||
defer server.Close() | ||
|
||
triggerConfig := trigger.Trigger{ | ||
Type: trigger.TriggerTypeHTTP, | ||
PlaywrightEngine: &trigger.PlaywrightEngineRequest{ | ||
Target: server.URL, | ||
Method: "basicTest", | ||
Script: script, | ||
}, | ||
} | ||
|
||
ex := triggerer.PLAYWRIGHTENGINE() | ||
|
||
resp, err := ex.Trigger(createContext(), triggerConfig, createOptions()) | ||
assert.NoError(t, err) | ||
|
||
assert.Equal(t, true, resp.Result.PlaywrightEngine.Success) | ||
} | ||
|
||
var scriptFail = ` | ||
const { expect } = require('@playwright/test'); | ||
async function basicTest(page) { | ||
await expect(page.getByText('NOT FOUND YORCH')).toBeVisible(); | ||
} | ||
module.exports = { basicTest }; | ||
` | ||
|
||
func TestTriggerFailure(t *testing.T) { | ||
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { | ||
|
||
assert.Equal(t, "GET", req.Method) | ||
|
||
rw.WriteHeader(200) | ||
_, err := rw.Write([]byte(`OK`)) | ||
assert.NoError(t, err) | ||
})) | ||
defer server.Close() | ||
|
||
triggerConfig := trigger.Trigger{ | ||
Type: trigger.TriggerTypeHTTP, | ||
PlaywrightEngine: &trigger.PlaywrightEngineRequest{ | ||
Target: server.URL, | ||
Method: "basicTest", | ||
Script: scriptFail, | ||
}, | ||
} | ||
|
||
ex := triggerer.PLAYWRIGHTENGINE() | ||
|
||
resp, err := ex.Trigger(createContext(), triggerConfig, createOptions()) | ||
assert.NotNil(t, err) | ||
|
||
assert.Equal(t, false, resp.Result.PlaywrightEngine.Success) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.