mirror of
https://github.com/hanzoai/team.git
synced 2026-09-30 01:57:35 +00:00
* Switch Cypress to use shared ESLint config * Run --fix in Cypress * Manually fix remaining lint issues in Cypress * Switch Playwright to use shared ESLint config * Run --fix in Playwright * Manually fix remaining lint issues in Playwright * Install and cache web app deps during Cypress CI builds This also caches the types and client package. That isn't needed currently since it uses prepackaged versions of those, but I imagine we might change that at some point. * Run e2e-tests-check when ESLint plugin is updated * Change E2E test GHA caching to cache all of web app node_modules * Fix mismatch between cache save and restore * Try bumping cache keys * Copy step to install dependencies to server.run_cypress.sh I don't know how this must've worked before, but if this fixes the issue, it seems like neither Cypress nor Playwright actually use the cached depenendencies. * Try disabling caching entirely for Cypress tests * Try bypassing makefile? * Try also manually building dependencies in run_specs.sh I don't know why this appears to duplicate run_cypress.sh and run_playwright.sh, both of which are called run_test.sh which might not be used any more as best I can tell. * Try installing the web app dependencies in yet another place * Disable the extra steps in server.prepare.sh specifically for Cypress * Revert changes to update cache key and disable web app depenedency cache on Cypress builds
568 lines
22 KiB
JavaScript
568 lines
22 KiB
JavaScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
// ***************************************************************
|
|
// - [#] indicates a test step (e.g. # Go to a page)
|
|
// - [*] indicates an assertion (e.g. * Check the title)
|
|
// - Use element ID when selecting an element. Create one if none.
|
|
// ***************************************************************
|
|
|
|
// Stage: @prod
|
|
// Group: @channels @interactive_dialog
|
|
|
|
/**
|
|
* Note: This test requires webhook server running. Initiate `npm run start:webhook` to start.
|
|
*/
|
|
|
|
let createdCommand;
|
|
|
|
describe('Interactive Dialog - Date and DateTime Fields', () => {
|
|
let testTeam;
|
|
let testChannel;
|
|
|
|
// Helper functions to reduce code duplication
|
|
const openDateTimeDialog = (command = '') => {
|
|
cy.postMessage(`/${createdCommand.trigger} ${command}`);
|
|
cy.get('#appsModal').should('be.visible');
|
|
};
|
|
|
|
const openDatePicker = (formGroupName) => {
|
|
cy.get('#appsModal').within(() => {
|
|
cy.contains('.form-group', formGroupName).within(() => {
|
|
cy.get('.date-time-input').click();
|
|
});
|
|
});
|
|
|
|
// Calendar should be visible with modal-overflow class automatically applied
|
|
cy.get('.rdp', {timeout: 5000}).should('be.visible');
|
|
};
|
|
|
|
// Helper to compute a day safely selectable in the date picker.
|
|
// Uses an offset from today to avoid midnight boundary issues.
|
|
// Returns {day: string, needsNextMonth: boolean}
|
|
const getSelectableDay = (daysFromToday = 2) => {
|
|
const now = new Date();
|
|
const today = now.getDate();
|
|
const lastDayOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate();
|
|
const targetDay = today + daysFromToday;
|
|
|
|
if (targetDay <= lastDayOfMonth) {
|
|
return {day: targetDay.toString(), needsNextMonth: false};
|
|
}
|
|
return {day: (targetDay - lastDayOfMonth).toString(), needsNextMonth: true};
|
|
};
|
|
|
|
const selectDateFromPicker = ({day, needsNextMonth = false}) => {
|
|
if (needsNextMonth) {
|
|
cy.get('.rdp .rdp-nav_button_next').click();
|
|
}
|
|
cy.get('.rdp').find('.rdp-day:not(.rdp-day_outside)').filter((i, el) => el.textContent.trim() === day).first().click();
|
|
};
|
|
|
|
const verifyModalTitle = (title) => {
|
|
cy.get('#appsModal').within(() => {
|
|
cy.get('#appsModalLabel').should('be.visible').and('contain', title);
|
|
});
|
|
};
|
|
|
|
const verifyFormGroup = (groupName, options = {}) => {
|
|
const selector = options.scrollIntoView ? cy.contains('.form-group', groupName).scrollIntoView().should('be.visible') : cy.contains('.form-group', groupName).should('be.visible');
|
|
|
|
return selector.within(() => {
|
|
if (options.label) {
|
|
cy.get('label').should('contain', options.label);
|
|
}
|
|
if (options.helpText) {
|
|
cy.get('.help-text').should('contain', options.helpText);
|
|
}
|
|
if (options.inputSelector) {
|
|
cy.get(options.inputSelector).should('be.visible');
|
|
}
|
|
});
|
|
};
|
|
|
|
before(() => {
|
|
cy.requireWebhookServer();
|
|
|
|
// # Use apiInitSetup like the working boolean test
|
|
cy.apiInitSetup().then(({team, channel}) => {
|
|
testTeam = team;
|
|
testChannel = channel;
|
|
|
|
const webhookBaseUrl = Cypress.expose().webhookBaseUrl;
|
|
|
|
const command = {
|
|
auto_complete: false,
|
|
description: 'Test for datetime dialog',
|
|
display_name: 'DateTime Dialog',
|
|
icon_url: '',
|
|
method: 'P',
|
|
team_id: team.id,
|
|
trigger: 'datetime_dialog',
|
|
url: `${webhookBaseUrl}/datetime_dialog_request`,
|
|
username: '',
|
|
};
|
|
|
|
cy.apiCreateCommand(command).then(({data}) => {
|
|
createdCommand = data;
|
|
|
|
// # Visit the test channel to ensure we're in the right place
|
|
cy.visit(`/${testTeam.name}/channels/${testChannel.name}`);
|
|
});
|
|
});
|
|
});
|
|
|
|
beforeEach(() => {
|
|
// # Ensure we're in the test channel before each test
|
|
cy.visit(`/${testTeam.name}/channels/${testChannel.name}`);
|
|
|
|
// # Wait for the channel to be fully loaded
|
|
cy.get('#postListContent').should('be.visible');
|
|
cy.get('#post_textbox').should('be.visible');
|
|
});
|
|
|
|
it('MM-T2530A - Date field UI and basic functionality', () => {
|
|
// # Open datetime dialog and verify modal
|
|
openDateTimeDialog('basic');
|
|
verifyModalTitle('DateTime Fields Test');
|
|
|
|
// * Verify the Event Date form group
|
|
verifyFormGroup('Event Date', {
|
|
label: 'Event Date',
|
|
helpText: 'Select the date for your event',
|
|
inputSelector: '.date-time-input',
|
|
});
|
|
|
|
// # Open date picker and select a date
|
|
openDatePicker('Event Date');
|
|
selectDateFromPicker(getSelectableDay());
|
|
|
|
// * Verify the selected date appears in the field
|
|
cy.get('#appsModal').within(() => {
|
|
cy.contains('.form-group', 'Event Date').within(() => {
|
|
cy.get('.date-time-input__value').should('be.visible').and('not.be.empty');
|
|
});
|
|
});
|
|
});
|
|
|
|
it('MM-T2530B - DateTime field UI and functionality', () => {
|
|
// # Open datetime dialog
|
|
openDateTimeDialog();
|
|
|
|
// * Verify the Meeting Time datetime field
|
|
verifyFormGroup('Meeting Time', {
|
|
label: 'Meeting Time',
|
|
helpText: 'Select the date and time for your meeting',
|
|
inputSelector: '.apps-form-datetime-input',
|
|
});
|
|
|
|
cy.get('#appsModal').within(() => {
|
|
// * Verify datetime input structure
|
|
cy.contains('.form-group', 'Meeting Time').within(() => {
|
|
cy.get('.apps-form-datetime-input').within(() => {
|
|
cy.get('.dateTime').should('be.visible');
|
|
cy.get('.dateTime__date').should('be.visible');
|
|
cy.get('.dateTime__time').should('be.visible');
|
|
});
|
|
});
|
|
|
|
// # Open date picker and select date
|
|
cy.contains('.form-group', 'Meeting Time').within(() => {
|
|
cy.get('.dateTime__date .date-time-input').click();
|
|
});
|
|
});
|
|
|
|
cy.get('.rdp', {timeout: 5000}).should('be.visible');
|
|
selectDateFromPicker(getSelectableDay(3));
|
|
|
|
// # Open time menu and select time
|
|
cy.get('#appsModal').within(() => {
|
|
cy.contains('.form-group', 'Meeting Time').within(() => {
|
|
cy.get('.dateTime__time button[data-testid="time_button"]').click();
|
|
});
|
|
});
|
|
|
|
cy.get('[id="expiryTimeMenu"]', {timeout: 10000}).should('be.visible');
|
|
cy.get('[id^="time_option_"]').first().click();
|
|
});
|
|
|
|
it('MM-T2530C - Date field validation with min_date constraint', () => {
|
|
// # Open datetime dialog
|
|
openDateTimeDialog('mindate');
|
|
|
|
// * Verify the Future Date Only field with min_date constraint
|
|
verifyFormGroup('Future Date Only', {
|
|
label: 'Future Date Only',
|
|
helpText: 'Must be today or later',
|
|
});
|
|
|
|
// # Open the date picker for constrained field
|
|
openDatePicker('Future Date Only');
|
|
|
|
// * Verify a past date is disabled (use 2 days ago to avoid midnight boundary)
|
|
// Navigate to previous month if the past date is in a different month
|
|
const pastDate = new Date();
|
|
pastDate.setDate(pastDate.getDate() - 2);
|
|
const needsPrevMonth = pastDate.getMonth() !== new Date().getMonth();
|
|
if (needsPrevMonth) {
|
|
cy.get('.rdp .rdp-nav_button_previous').click();
|
|
}
|
|
const pastDay = pastDate.getDate().toString();
|
|
cy.get('.rdp').find('.rdp-day:not(.rdp-day_outside)').
|
|
filter((i, el) => el.textContent.trim() === pastDay).
|
|
should('have.class', 'rdp-day_disabled').and('be.disabled');
|
|
|
|
// * Verify a future date is enabled and select it (use +2 days for midnight safety)
|
|
const {day: futureDay, needsNextMonth} = getSelectableDay(2);
|
|
if (needsPrevMonth) {
|
|
// Return to current month after validating a past date in previous month
|
|
cy.get('.rdp .rdp-nav_button_next').click();
|
|
}
|
|
if (needsNextMonth) {
|
|
cy.get('.rdp .rdp-nav_button_next').click();
|
|
}
|
|
cy.get('.rdp').find('.rdp-day:not(.rdp-day_outside)').
|
|
filter((i, el) => el.textContent.trim() === futureDay).
|
|
should('not.have.class', 'rdp-day_disabled').and('not.be.disabled').
|
|
first().click();
|
|
|
|
// * Verify date selection
|
|
cy.get('#appsModal').within(() => {
|
|
cy.contains('.form-group', 'Future Date Only').within(() => {
|
|
cy.get('.date-time-input__value').should('be.visible').and('not.be.empty');
|
|
});
|
|
});
|
|
});
|
|
|
|
it('MM-T2530D - DateTime field with custom time interval', () => {
|
|
// # Open datetime dialog with interval command
|
|
cy.get('#postListContent').should('be.visible');
|
|
openDateTimeDialog('interval');
|
|
|
|
// * Verify custom interval datetime field
|
|
verifyFormGroup('Custom Interval Time', {
|
|
inputSelector: '.apps-form-datetime-input',
|
|
scrollIntoView: true,
|
|
});
|
|
|
|
// # Open time menu
|
|
cy.get('#appsModal').within(() => {
|
|
cy.contains('.form-group', 'Custom Interval Time').within(() => {
|
|
cy.get('.dateTime__time button[data-testid="time_button"]').click();
|
|
});
|
|
});
|
|
|
|
// * Verify time menu with custom intervals
|
|
cy.get('[id="expiryTimeMenu"]', {timeout: 10000}).should('be.visible');
|
|
cy.get('[id^="time_option_"]').should('have.length.greaterThan', 0);
|
|
});
|
|
|
|
it('MM-T2530E - Form submission with date and datetime values', () => {
|
|
// # Open dialog and select date
|
|
openDateTimeDialog('basic');
|
|
openDatePicker('Event Date');
|
|
selectDateFromPicker(getSelectableDay());
|
|
|
|
// # Submit the form
|
|
cy.get('#appsModal').within(() => {
|
|
cy.get('#appsModalSubmit').click();
|
|
});
|
|
|
|
// * Verify submission success
|
|
cy.get('#appsModal', {timeout: 10000}).should('not.exist');
|
|
cy.get('#postListContent', {timeout: 10000}).within(() => {
|
|
cy.get('.post-message__text').last().should('contain', 'Form submitted successfully');
|
|
});
|
|
});
|
|
|
|
it('MM-T2530F - Relative date values functionality', () => {
|
|
// # Open datetime dialog
|
|
openDateTimeDialog('relative');
|
|
|
|
// * Verify relative date field with 'today' default is pre-populated
|
|
cy.get('#appsModal').within(() => {
|
|
cy.contains('.form-group', 'Relative Date Example').scrollIntoView().should('be.visible').within(() => {
|
|
cy.get('.date-time-input__value').should('be.visible').and('not.be.empty');
|
|
});
|
|
|
|
// * Verify relative datetime field with '+1d' default is pre-populated
|
|
cy.contains('.form-group', 'Relative DateTime Example').scrollIntoView().should('be.visible').within(() => {
|
|
cy.get('.apps-form-datetime-input').should('not.be.empty');
|
|
});
|
|
});
|
|
});
|
|
|
|
it('MM-T2530G - Date field locale formatting', () => {
|
|
// # Set browser locale to en-US for consistent formatting
|
|
cy.visit(`/${testTeam.name}/channels/${testChannel.name}`, {
|
|
onBeforeLoad(win) {
|
|
Object.defineProperty(win.navigator, 'language', {value: 'en-US'});
|
|
Object.defineProperty(win.navigator, 'languages', {value: ['en-US', 'en']});
|
|
},
|
|
});
|
|
|
|
// # Open dialog, select date, and verify locale formatting
|
|
openDateTimeDialog('basic');
|
|
openDatePicker('Event Date');
|
|
const selectedDay = getSelectableDay();
|
|
selectDateFromPicker(selectedDay);
|
|
|
|
// * Verify en-US locale formatting (e.g., "Aug 10, 2025")
|
|
cy.get('#appsModal').within(() => {
|
|
cy.contains('.form-group', 'Event Date').within(() => {
|
|
cy.get('.date-time-input__value').should('be.visible').and('not.be.empty').invoke('text').then((text) => {
|
|
const match = text.trim().match(/^[A-Z][a-z]{2} (\d{1,2}), \d{4}$/);
|
|
expect(match, 'date format').to.not.be.null;
|
|
expect(Number(match[1]), 'selected day').to.equal(Number(selectedDay.day));
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('MM-T2530H - DateTime field respects 12h/24h time preference', () => {
|
|
// # Set user preference to 24-hour time
|
|
cy.apiSaveClockDisplayModeTo24HourPreference(true);
|
|
|
|
cy.reload();
|
|
cy.get('#postListContent').should('be.visible');
|
|
|
|
// # Open datetime dialog
|
|
openDateTimeDialog();
|
|
|
|
// * Verify Meeting Time field
|
|
verifyFormGroup('Meeting Time', {
|
|
inputSelector: '.apps-form-datetime-input',
|
|
});
|
|
|
|
// # Select a date
|
|
cy.get('#appsModal').within(() => {
|
|
cy.contains('.form-group', 'Meeting Time').within(() => {
|
|
cy.get('.dateTime__date .date-time-input').click();
|
|
});
|
|
});
|
|
|
|
cy.get('.rdp', {timeout: 5000}).should('be.visible');
|
|
selectDateFromPicker(getSelectableDay());
|
|
|
|
// # Open time menu
|
|
cy.get('#appsModal').within(() => {
|
|
cy.contains('.form-group', 'Meeting Time').within(() => {
|
|
cy.get('.dateTime__time button[data-testid="time_button"]').click();
|
|
});
|
|
});
|
|
|
|
// * Verify 24-hour format in dropdown (e.g., "14:00" not "2:00 PM")
|
|
cy.get('[id="expiryTimeMenu"]', {timeout: 10000}).should('be.visible');
|
|
cy.get('[id^="time_option_"]').first().invoke('text').then((text) => {
|
|
expect(text).to.match(/^\d{2}:\d{2}$/); // 24-hour format: HH:MM
|
|
});
|
|
|
|
// # Select a time
|
|
cy.get('[id^="time_option_"]').eq(5).click();
|
|
|
|
// * Verify selected time shows in 24-hour format
|
|
cy.get('#appsModal').within(() => {
|
|
cy.contains('.form-group', 'Meeting Time').within(() => {
|
|
cy.get('.dateTime__time .date-time-input__value').invoke('text').then((text) => {
|
|
expect(text).to.match(/^\d{2}:\d{2}$/);
|
|
});
|
|
});
|
|
});
|
|
|
|
// # Close dialog
|
|
cy.get('#appsModal').within(() => {
|
|
cy.get('#appsModalCancel').click();
|
|
});
|
|
|
|
// # Set user preference to 12-hour time
|
|
cy.apiSaveClockDisplayModeTo24HourPreference(false);
|
|
|
|
cy.reload();
|
|
cy.get('#postListContent').should('be.visible');
|
|
|
|
// # Open dialog again
|
|
openDateTimeDialog();
|
|
|
|
// # Select date and open time menu
|
|
cy.get('#appsModal').within(() => {
|
|
cy.contains('.form-group', 'Meeting Time').within(() => {
|
|
cy.get('.dateTime__date .date-time-input').click();
|
|
});
|
|
});
|
|
|
|
cy.get('.rdp').should('be.visible');
|
|
selectDateFromPicker(getSelectableDay(3));
|
|
|
|
cy.get('#appsModal').within(() => {
|
|
cy.contains('.form-group', 'Meeting Time').within(() => {
|
|
cy.get('.dateTime__time button[data-testid="time_button"]').click();
|
|
});
|
|
});
|
|
|
|
// * Verify 12-hour format in dropdown (e.g., "2:00 PM" not "14:00")
|
|
cy.get('[id="expiryTimeMenu"]').should('be.visible');
|
|
cy.get('[id^="time_option_"]').first().invoke('text').then((text) => {
|
|
expect(text).to.match(/\d{1,2}:\d{2} [AP]M/); // 12-hour format: H:MM AM/PM
|
|
});
|
|
});
|
|
|
|
it('MM-T2530O - Manual time entry (basic functionality)', () => {
|
|
// # Open timezone-manual dialog via webhook
|
|
openDateTimeDialog('timezone-manual');
|
|
verifyModalTitle('Timezone & Manual Entry Demo');
|
|
|
|
// * Verify local manual entry field exists
|
|
verifyFormGroup('Your Local Time (Manual Entry)', {
|
|
helpText: 'Type any time',
|
|
});
|
|
|
|
// # Type a time in manual entry field
|
|
cy.get('#appsModal').within(() => {
|
|
cy.contains('.form-group', 'Your Local Time (Manual Entry)').within(() => {
|
|
cy.get('input#time_input').should('be.visible').type('3:45pm').blur();
|
|
});
|
|
});
|
|
|
|
// * Verify time is accepted (no error state)
|
|
cy.contains('.form-group', 'Your Local Time (Manual Entry)').within(() => {
|
|
cy.get('input#time_input').should('not.have.class', 'error');
|
|
cy.get('input#time_input').should('have.value', '3:45 PM');
|
|
});
|
|
|
|
// # Submit form
|
|
cy.get('#appsModal').within(() => {
|
|
cy.get('#appsModalSubmit').click();
|
|
});
|
|
|
|
// * Verify submission success
|
|
cy.get('#appsModal', {timeout: 10000}).should('not.exist');
|
|
});
|
|
|
|
it('MM-T2530P - Manual time entry (multiple formats)', () => {
|
|
openDateTimeDialog('timezone-manual');
|
|
|
|
const testFormats = [
|
|
{input: '12a', expected12h: '12:00 AM'},
|
|
{input: '14:30', expected12h: '2:30 PM'},
|
|
{input: '9pm', expected12h: '9:00 PM'},
|
|
];
|
|
|
|
testFormats.forEach(({input, expected12h}) => {
|
|
cy.contains('.form-group', 'Your Local Time (Manual Entry)').within(() => {
|
|
cy.get('input#time_input').clear().type(input).blur();
|
|
|
|
// Wait for formatting to apply
|
|
cy.wait(100);
|
|
|
|
// Verify time is formatted correctly (assumes 12h preference for test consistency)
|
|
cy.get('input#time_input').invoke('val').should('equal', expected12h);
|
|
});
|
|
});
|
|
});
|
|
|
|
it('MM-T2530Q - Manual time entry (invalid format)', () => {
|
|
openDateTimeDialog('timezone-manual');
|
|
|
|
// # Type invalid time
|
|
cy.contains('.form-group', 'Your Local Time (Manual Entry)').within(() => {
|
|
cy.get('input#time_input').type('abc').blur();
|
|
|
|
// * Verify error state
|
|
cy.get('input#time_input').should('have.class', 'error');
|
|
});
|
|
|
|
// # Type valid time
|
|
cy.contains('.form-group', 'Your Local Time (Manual Entry)').within(() => {
|
|
cy.get('input#time_input').clear().type('2:30pm').blur();
|
|
|
|
// * Verify error clears
|
|
cy.get('input#time_input').should('not.have.class', 'error');
|
|
});
|
|
});
|
|
|
|
it('MM-T2530R - Timezone support (dropdown)', function() {
|
|
// Skip if running in London timezone (can't test timezone conversion)
|
|
const userTimezone = new Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
if (userTimezone === 'Europe/London' || userTimezone === 'GMT' || userTimezone.includes('London')) {
|
|
this.skip();
|
|
}
|
|
|
|
openDateTimeDialog('timezone-manual');
|
|
|
|
// * Verify timezone indicator is shown
|
|
cy.contains('.form-group', 'London Office Hours (Dropdown)').within(() => {
|
|
cy.contains('Times in GMT').should('be.visible');
|
|
});
|
|
|
|
// # Select a date
|
|
cy.contains('.form-group', 'London Office Hours (Dropdown)').within(() => {
|
|
cy.get('.dateTime__date .date-time-input').click();
|
|
});
|
|
|
|
cy.get('.rdp').should('be.visible');
|
|
selectDateFromPicker(getSelectableDay());
|
|
|
|
// # Open time dropdown
|
|
cy.contains('.form-group', 'London Office Hours (Dropdown)').within(() => {
|
|
cy.get('.dateTime__time button[data-testid="time_button"]').click();
|
|
});
|
|
|
|
// * Verify dropdown shows times starting at midnight (London time)
|
|
cy.get('[id="expiryTimeMenu"]').should('be.visible');
|
|
cy.get('[id^="time_option_"]').first().invoke('text').then((text) => {
|
|
// Should show midnight in 12h or 24h format
|
|
expect(text).to.match(/^(12:00 AM|00:00)$/);
|
|
});
|
|
|
|
// # Select a time
|
|
cy.get('[id^="time_option_"]').eq(5).click();
|
|
|
|
// # Submit form
|
|
cy.get('#appsModal').within(() => {
|
|
cy.get('#appsModalSubmit').click();
|
|
});
|
|
|
|
// * Verify submission success (UTC conversion verified server-side)
|
|
cy.get('#appsModal', {timeout: 10000}).should('not.exist');
|
|
});
|
|
|
|
it('MM-T2530S - Timezone support (manual entry)', function() {
|
|
// Skip if running in London timezone
|
|
const userTimezone = new Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
if (userTimezone === 'Europe/London' || userTimezone === 'GMT' || userTimezone.includes('London')) {
|
|
this.skip();
|
|
}
|
|
|
|
openDateTimeDialog('timezone-manual');
|
|
|
|
// * Verify timezone indicator is shown
|
|
cy.contains('.form-group', 'London Office Hours (Manual Entry)').within(() => {
|
|
cy.contains('Times in GMT').should('be.visible');
|
|
});
|
|
|
|
// # Select date
|
|
cy.contains('.form-group', 'London Office Hours (Manual Entry)').within(() => {
|
|
cy.get('.dateTime__date .date-time-input').click();
|
|
});
|
|
|
|
cy.get('.rdp').should('be.visible');
|
|
selectDateFromPicker(getSelectableDay());
|
|
|
|
// # Type time in manual entry
|
|
cy.contains('.form-group', 'London Office Hours (Manual Entry)').within(() => {
|
|
cy.get('input#time_input').clear().type('2:30pm').blur();
|
|
|
|
// * Verify time is accepted
|
|
cy.get('input#time_input').should('not.have.class', 'error');
|
|
});
|
|
|
|
// # Submit form
|
|
cy.get('#appsModal').within(() => {
|
|
cy.get('#appsModalSubmit').click();
|
|
});
|
|
|
|
// * Verify submission success (timezone conversion happens server-side)
|
|
cy.get('#appsModal', {timeout: 10000}).should('not.exist');
|
|
});
|
|
});
|