Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into SEC-66-freeze-nativ…
Browse files Browse the repository at this point in the history
…e-prototypes-2
  • Loading branch information
netroy committed Aug 13, 2024
2 parents 2df2614 + 117e2d9 commit 2c67421
Show file tree
Hide file tree
Showing 149 changed files with 4,841 additions and 3,592 deletions.
2 changes: 1 addition & 1 deletion .github/scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"debug": "4.3.4",
"glob": "10.3.10",
"p-limit": "3.1.0",
"picocolors": "1.0.0",
"picocolors": "1.0.1",
"semver": "7.5.4",
"tempfile": "5.0.0",
"typescript": "*"
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/units-tests-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ jobs:
run: pnpm install --frozen-lockfile

- name: Setup build cache
if: inputs.collectCoverage != true
uses: rharkor/caching-for-turbo@v1.5

- name: Build
Expand Down
21 changes: 12 additions & 9 deletions cypress/composables/projects.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CredentialsModal, WorkflowPage } from '../pages';
import { getVisibleSelect } from '../utils';

const workflowPage = new WorkflowPage();
const credentialsModal = new CredentialsModal();
Expand All @@ -11,18 +12,25 @@ export const getProjectTabs = () => cy.getByTestId('project-tabs').find('a');
export const getProjectTabWorkflows = () => getProjectTabs().filter('a[href$="/workflows"]');
export const getProjectTabCredentials = () => getProjectTabs().filter('a[href$="/credentials"]');
export const getProjectTabSettings = () => getProjectTabs().filter('a[href$="/settings"]');
export const getProjectSettingsNameInput = () => cy.getByTestId('project-settings-name-input');
export const getProjectSettingsNameInput = () =>
cy.getByTestId('project-settings-name-input').find('input');
export const getProjectSettingsSaveButton = () => cy.getByTestId('project-settings-save-button');
export const getProjectSettingsCancelButton = () =>
cy.getByTestId('project-settings-cancel-button');
export const getProjectSettingsDeleteButton = () =>
cy.getByTestId('project-settings-delete-button');
export const getProjectMembersSelect = () => cy.getByTestId('project-members-select');
export const addProjectMember = (email: string) => {
export const addProjectMember = (email: string, role?: string) => {
getProjectMembersSelect().click();
getProjectMembersSelect().get('.el-select-dropdown__item').contains(email.toLowerCase()).click();

if (role) {
cy.getByTestId(`user-list-item-${email}`)
.find('[data-test-id="projects-settings-user-role-select"]')
.click();
getVisibleSelect().find('li').contains(role).click();
}
};
export const getProjectNameInput = () => cy.get('#projectName').find('input');
export const getResourceMoveModal = () => cy.getByTestId('project-move-resource-modal');
export const getResourceMoveConfirmModal = () =>
cy.getByTestId('project-move-resource-confirm-modal');
Expand All @@ -31,12 +39,7 @@ export const getProjectMoveSelect = () => cy.getByTestId('project-move-resource-
export function createProject(name: string) {
getAddProjectButton().click();

getProjectNameInput()
.should('be.visible')
.should('be.focused')
.should('have.value', 'My project')
.clear()
.type(name);
getProjectSettingsNameInput().should('be.visible').clear().type(name);
getProjectSettingsSaveButton().click();
}

Expand Down
11 changes: 10 additions & 1 deletion cypress/e2e/12-canvas-actions.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,16 @@ describe('Canvas Actions', () => {
});
});

it('should delete connections by pressing the delete button', () => {
it('should delete node by pressing keyboard backspace', () => {
WorkflowPage.actions.addNodeToCanvas(MANUAL_TRIGGER_NODE_NAME);
WorkflowPage.getters.canvasNodeByName(MANUAL_TRIGGER_NODE_DISPLAY_NAME).click();
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
WorkflowPage.getters.canvasNodeByName(CODE_NODE_NAME).click();
cy.get('body').type('{backspace}');
WorkflowPage.getters.nodeConnections().should('have.length', 0);
});

it('should delete connections by clicking on the delete button', () => {
WorkflowPage.actions.addNodeToCanvas(MANUAL_TRIGGER_NODE_NAME);
WorkflowPage.getters.canvasNodeByName(MANUAL_TRIGGER_NODE_DISPLAY_NAME).click();
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
Expand Down
43 changes: 33 additions & 10 deletions cypress/e2e/14-mapping.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('Data mapping', () => {
ndv.actions.mapDataFromHeader(2, 'value');
ndv.getters
.inlineExpressionEditorInput()
.should('have.text', "{{ $json.timestamp }} {{ $json['Readable date'] }}");
.should('have.text', "{{ $json['Readable date'] }}{{ $json.timestamp }}");
});

it('maps expressions from table json, and resolves value based on hover', () => {
Expand Down Expand Up @@ -145,8 +145,8 @@ describe('Data mapping', () => {
ndv.actions.mapToParameter('value');
ndv.getters
.inlineExpressionEditorInput()
.should('have.text', '{{ $json.input[0].count }} {{ $json.input }}');
ndv.actions.validateExpressionPreview('value', '0 [object Object]');
.should('have.text', '{{ $json.input }}{{ $json.input[0].count }}');
ndv.actions.validateExpressionPreview('value', '[object Object]0');
});

it('maps expressions from schema view', () => {
Expand All @@ -170,8 +170,8 @@ describe('Data mapping', () => {
ndv.actions.mapToParameter('value');
ndv.getters
.inlineExpressionEditorInput()
.should('have.text', '{{ $json.input[0].count }} {{ $json.input }}');
ndv.actions.validateExpressionPreview('value', '0 [object Object]');
.should('have.text', '{{ $json.input }}{{ $json.input[0].count }}');
ndv.actions.validateExpressionPreview('value', '[object Object]0');
});

it('maps expressions from previous nodes', () => {
Expand Down Expand Up @@ -200,17 +200,17 @@ describe('Data mapping', () => {
.inlineExpressionEditorInput()
.should(
'have.text',
`{{ $('${SCHEDULE_TRIGGER_NODE_NAME}').item.json.input[0].count }} {{ $('${SCHEDULE_TRIGGER_NODE_NAME}').item.json.input }}`,
`{{ $('${SCHEDULE_TRIGGER_NODE_NAME}').item.json.input }}{{ $('${SCHEDULE_TRIGGER_NODE_NAME}').item.json.input[0].count }}`,
);

ndv.actions.selectInputNode('Set');

ndv.getters.executingLoader().should('not.exist');
ndv.getters.inputDataContainer().should('exist');
ndv.actions.validateExpressionPreview('value', '0 [object Object]');
ndv.actions.validateExpressionPreview('value', '[object Object]0');

ndv.getters.inputTbodyCell(2, 0).realHover();
ndv.actions.validateExpressionPreview('value', '1 [object Object]');
ndv.actions.validateExpressionPreview('value', '[object Object]1');
});

it('maps keys to path', () => {
Expand Down Expand Up @@ -284,8 +284,8 @@ describe('Data mapping', () => {
ndv.actions.mapToParameter('value');
ndv.getters
.inlineExpressionEditorInput()
.should('have.text', '{{ $json.input[0].count }} {{ $json.input }}');
ndv.actions.validateExpressionPreview('value', '0 [object Object]');
.should('have.text', '{{ $json.input }}{{ $json.input[0].count }}');
ndv.actions.validateExpressionPreview('value', '[object Object]0');
});

it('renders expression preview when a previous node is selected', () => {
Expand Down Expand Up @@ -342,4 +342,27 @@ describe('Data mapping', () => {
.invoke('css', 'border')
.should('include', 'dashed rgb(90, 76, 194)');
});

it('maps expressions to a specific location in the editor', () => {
cy.fixture('Test_workflow_3.json').then((data) => {
cy.get('body').paste(JSON.stringify(data));
});
workflowPage.actions.zoomToFit();

workflowPage.actions.openNode('Set');
ndv.actions.clearParameterInput('value');
ndv.actions.typeIntoParameterInput('value', '=');
ndv.actions.typeIntoParameterInput('value', 'hello world{enter}{enter}newline');

ndv.getters.inputDataContainer().should('exist').find('span').contains('count').realMouseDown();

ndv.actions.mapToParameter('value');

ndv.getters.inputDataContainer().find('span').contains('input').realMouseDown();
ndv.actions.mapToParameter('value', 'bottom');

ndv.getters
.inlineExpressionEditorInput()
.should('have.text', '{{ $json.input[0].count }}hello worldnewline{{ $json.input }}');
});
});
39 changes: 29 additions & 10 deletions cypress/e2e/17-sharing.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ describe('Sharing', { disableAutoLogin: true }, () => {
describe('Credential Usage in Cross Shared Workflows', () => {
beforeEach(() => {
cy.resetDatabase();
cy.enableFeature('sharing');
cy.enableFeature('advancedPermissions');
cy.enableFeature('projectRole:admin');
cy.enableFeature('projectRole:editor');
Expand All @@ -274,11 +275,6 @@ describe('Credential Usage in Cross Shared Workflows', () => {
});

it('should only show credentials from the same team project', () => {
cy.enableFeature('advancedPermissions');
cy.enableFeature('projectRole:admin');
cy.enableFeature('projectRole:editor');
cy.changeQuota('maxTeamProjects', -1);

// Create a notion credential in the home project
credentialsPage.getters.emptyListCreateCredentialButton().click();
credentialsModal.actions.createNewCredential('Notion API');
Expand All @@ -305,10 +301,36 @@ describe('Credential Usage in Cross Shared Workflows', () => {
getVisibleSelect().find('li').should('have.length', 2);
});

it('should only show credentials in their personal project for members', () => {
// Create a notion credential as the owner
credentialsPage.getters.emptyListCreateCredentialButton().click();
credentialsModal.actions.createNewCredential('Notion API');

// Create another notion credential as the owner, but share it with member
// 0
credentialsPage.getters.createCredentialButton().click();
credentialsModal.actions.createNewCredential('Notion API', false);
credentialsModal.actions.changeTab('Sharing');
credentialsModal.actions.addUser(INSTANCE_MEMBERS[0].email);
credentialsModal.actions.saveSharing();

// As the member, create a new notion credential and a workflow
cy.signinAsMember();
cy.visit(credentialsPage.url);
credentialsPage.getters.createCredentialButton().click();
credentialsModal.actions.createNewCredential('Notion API');
cy.visit(workflowsPage.url);
workflowsPage.actions.createWorkflowFromCard();
workflowPage.actions.addNodeToCanvas(NOTION_NODE_NAME, true, true);

// Only the own credential the shared one (+ the 'Create new' option)
// should be in the dropdown
workflowPage.getters.nodeCredentialsSelect().click();
getVisibleSelect().find('li').should('have.length', 3);
});

it('should only show credentials in their personal project for members if the workflow was shared with them', () => {
const workflowName = 'Test workflow';
cy.enableFeature('sharing');
cy.reload();

// Create a notion credential as the owner and a workflow that is shared
// with member 0
Expand Down Expand Up @@ -339,7 +361,6 @@ describe('Credential Usage in Cross Shared Workflows', () => {

it("should show all credentials from all personal projects the workflow's been shared into for the global owner", () => {
const workflowName = 'Test workflow';
cy.enableFeature('sharing');

// As member 1, create a new notion credential. This should not show up.
cy.signinAsMember(1);
Expand Down Expand Up @@ -384,8 +405,6 @@ describe('Credential Usage in Cross Shared Workflows', () => {
});

it('should show all personal credentials if the global owner owns the workflow', () => {
cy.enableFeature('sharing');

// As member 0, create a new notion credential.
cy.signinAsMember();
cy.visit(credentialsPage.url);
Expand Down
Loading

0 comments on commit 2c67421

Please sign in to comment.