From ed1bb98b61457472f062757e4357f1d7e9c5e2f5 Mon Sep 17 00:00:00 2001 From: Paul Clue <67766160+Paul-Clue@users.noreply.github.com> Date: Tue, 18 Jul 2023 14:29:28 -0500 Subject: [PATCH 1/2] Add at browser association --- server/apps/embed.js | 93 ++++++------------- server/graphql-schema.js | 8 ++ server/handlebars/helpers/index.js | 2 +- server/models/At.js | 8 +- server/models/AtBrowsers.js | 29 ++++++ server/models/Browser.js | 11 +++ server/models/services/AtService.js | 32 ++++++- server/models/services/BrowserService.js | 43 ++++++++- server/resolvers/atsResolver.js | 1 + server/resolvers/browsersResolver.js | 2 +- server/seeders/20230622202911-addAtBrowser.js | 34 +++++++ server/tests/integration/graphql.test.js | 10 ++ .../tests/models/services/AtService.test.js | 25 ++++- .../models/services/BrowserService.test.js | 36 +++++-- 14 files changed, 248 insertions(+), 86 deletions(-) create mode 100644 server/models/AtBrowsers.js create mode 100644 server/seeders/20230622202911-addAtBrowser.js diff --git a/server/apps/embed.js b/server/apps/embed.js index f3aa9fa78..ccdda3a28 100644 --- a/server/apps/embed.js +++ b/server/apps/embed.js @@ -33,17 +33,20 @@ app.set('views', resolve(handlebarsPath, 'views')); const millisecondsUntilStale = 5000; // TODO: Provide through resolvers -const validAtBrowserCombinations = { - JAWS: new Set(['Firefox', 'Chrome']), - NVDA: new Set(['Firefox', 'Chrome']), - 'VoiceOver for macOS': new Set(['Firefox', 'Chrome', 'Safari']) -}; const queryReports = async () => { const { data, errors } = await apolloServer.executeOperation({ query: gql` query { - testPlanReports(statuses: [DRAFT, CANDIDATE, RECOMMENDED]) { + ats { + id + name + browsers { + id + name + } + } + testPlanReports(statuses: [CANDIDATE, RECOMMENDED]) { id metrics status @@ -85,7 +88,11 @@ const queryReports = async () => { const reportsHashed = hash(data.testPlanReports); - return { allTestPlanReports: data.testPlanReports, reportsHashed }; + return { + allTestPlanReports: data.testPlanReports, + reportsHashed, + ats: data.ats + }; }; // As of now, a full query for the complete list of reports is needed to build @@ -99,10 +106,7 @@ const getLatestReportsForPattern = ({ allTestPlanReports, pattern }) => { let title; const testPlanReports = allTestPlanReports.filter(report => { - if ( - report.testPlanVersion.testPlan.id === pattern && - report.status !== 'DRAFT' - ) { + if (report.testPlanVersion.testPlan.id === pattern) { title = report.testPlanVersion.title; return true; } @@ -197,56 +201,8 @@ const getLatestReportsForPattern = ({ allTestPlanReports, pattern }) => { }; }; -// This function gets all the AT + Browser Combinations which have been added to the Test Queue at -// some point; this means if the combination has never been added, a valid combination will be -// marked as 'Not Applicable' rather than 'Data Not Yet Available'. -/*const getAllAtBrowserCombinations = reports => { - const combinations = {}; - - reports.forEach(report => { - if (!(report.at.name in combinations)) { - combinations[report.at.name] = new Set(); - } - combinations[report.at.name].add(report.browser.name); - }); - - return combinations; -};*/ - -// TODO: Provide through resolvers -// Check if the applicable ATs reported for the tests found for a report link to an already known -// reference of which ATs match against which browsers -const getAllAtBrowserCombinations = reports => { - const combinations = {}; - const loggedAtIds = []; - - const report = reports[0]; - report.testPlanVersion.tests.forEach(test => { - const atIds = test.ats.map(at => at.id); - - if (!loggedAtIds.includes(1) && atIds.includes('1')) { - combinations[Object.keys(validAtBrowserCombinations)[0]] = - Object.values(validAtBrowserCombinations)[0]; - loggedAtIds.push(1); - } - - if (!loggedAtIds.includes(2) && atIds.includes('2')) { - combinations[Object.keys(validAtBrowserCombinations)[1]] = - Object.values(validAtBrowserCombinations)[1]; - loggedAtIds.push(2); - } - - if (!loggedAtIds.includes(3) && atIds.includes('3')) { - combinations[Object.keys(validAtBrowserCombinations)[2]] = - Object.values(validAtBrowserCombinations)[2]; - loggedAtIds.push(3); - } - }); - - return combinations; -}; - const renderEmbed = ({ + ats, allTestPlanReports, queryTitle, pattern, @@ -261,8 +217,17 @@ const renderEmbed = ({ status, reportsByAt } = getLatestReportsForPattern({ pattern, allTestPlanReports }); - const allAtBrowserCombinations = - getAllAtBrowserCombinations(allTestPlanReports); + const allAtBrowserCombinations = Object.fromEntries( + ats.map(at => { + return [ + at.name, + at.browsers.map(browser => { + return browser.name; + }) + ]; + }) + ); + return hbs.renderView(resolve(handlebarsPath, 'views/main.hbs'), { layout: 'index', dataEmpty: Object.keys(reportsByAt).length === 0, @@ -298,8 +263,10 @@ app.get('/reports/:pattern', async (req, res) => { const protocol = /dev|vagrant/.test(process.env.ENVIRONMENT) ? 'http://' : 'https://'; - const { allTestPlanReports, reportsHashed } = await queryReportsCached(); + const { allTestPlanReports, reportsHashed, ats } = + await queryReportsCached(); const embedRendered = await renderEmbedCached({ + ats, allTestPlanReports, reportsHashed, queryTitle, diff --git a/server/graphql-schema.js b/server/graphql-schema.js index 4dcbf6983..e65def618 100644 --- a/server/graphql-schema.js +++ b/server/graphql-schema.js @@ -83,6 +83,10 @@ const graphqlSchema = gql` A fully-qualified version like "99.0.4844.84" """ browserVersions: [BrowserVersion]! + """ + The Ats which can be run with the specific browser, for example, Jaws can be run with Chrome but not Safari, and Safari works with VoiceOver only. + """ + ats: [At]! } """ @@ -145,6 +149,10 @@ const graphqlSchema = gql` # """ # modes: [AtMode]! atVersions: [AtVersion]! + """ + The browsers which can run the At, for example, Safari can run VoiceOver but not Jaws because Jaws is Windows only. + """ + browsers: [Browser]! } """ diff --git a/server/handlebars/helpers/index.js b/server/handlebars/helpers/index.js index e4c230826..12347364d 100644 --- a/server/handlebars/helpers/index.js +++ b/server/handlebars/helpers/index.js @@ -14,7 +14,7 @@ module.exports = { return object.allAtVersionsByAt[key].name; }, combinationExists: function (object, atName, browserName) { - if (object.allAtBrowserCombinations[atName].has(browserName)) { + if (object.allAtBrowserCombinations[atName].includes(browserName)) { return true; } return false; diff --git a/server/models/At.js b/server/models/At.js index a97e85ad7..334739e5e 100644 --- a/server/models/At.js +++ b/server/models/At.js @@ -22,7 +22,7 @@ module.exports = function (sequelize, DataTypes) { ); Model.AT_VERSION_ASSOCIATION = { as: 'atVersions' }; - + Model.BROWSERS_ASSOCIATION = { through: 'AtBrowsers', as: 'browsers' }; Model.AT_MODE_ASSOCIATION = { as: 'modes' }; Model.associate = function (models) { @@ -32,6 +32,12 @@ module.exports = function (sequelize, DataTypes) { sourceKey: 'id' }); + Model.belongsToMany(models.Browser, { + ...Model.BROWSERS_ASSOCIATION, + foreignKey: 'atId', + otherKey: 'browserId' + }); + Model.hasMany(models.AtMode, { ...Model.AT_MODE_ASSOCIATION, foreignKey: 'atId', diff --git a/server/models/AtBrowsers.js b/server/models/AtBrowsers.js new file mode 100644 index 000000000..b6a984ca3 --- /dev/null +++ b/server/models/AtBrowsers.js @@ -0,0 +1,29 @@ +const MODEL_NAME = 'AtBrowsers'; + +module.exports = function (sequelize, DataTypes) { + return sequelize.define( + MODEL_NAME, + { + atId: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'At', + key: 'id' + } + }, + browserId: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'Browser', + key: 'id' + } + } + }, + { + timestamps: false, + tableName: MODEL_NAME + } + ); +}; diff --git a/server/models/Browser.js b/server/models/Browser.js index 224308b9b..4580893a6 100644 --- a/server/models/Browser.js +++ b/server/models/Browser.js @@ -27,12 +27,23 @@ module.exports = function (sequelize, DataTypes) { Model.BROWSER_VERSION_ASSOCIATION = { as: 'browserVersions' }; + Model.ATS_ASSOCIATION = { + through: 'AtBrowsers', + as: 'ats' + }; + Model.associate = function (models) { Model.hasMany(models.BrowserVersion, { ...Model.BROWSER_VERSION_ASSOCIATION, foreignKey: 'browserId', sourceKey: 'id' }); + + Model.belongsToMany(models.At, { + ...Model.ATS_ASSOCIATION, + foreignKey: 'browserId', + otherKey: 'atId' + }); }; return Model; diff --git a/server/models/services/AtService.js b/server/models/services/AtService.js index ef015cccb..372ea1519 100644 --- a/server/models/services/AtService.js +++ b/server/models/services/AtService.js @@ -3,7 +3,8 @@ const ModelService = require('./ModelService'); const { AT_ATTRIBUTES, AT_VERSION_ATTRIBUTES, - AT_MODE_ATTRIBUTES + AT_MODE_ATTRIBUTES, + BROWSER_ATTRIBUTES } = require('./helpers'); const { Sequelize, At, AtVersion, AtMode } = require('../'); const { Op } = Sequelize; @@ -37,6 +38,15 @@ const atModeAssociation = atModeAttributes => ({ attributes: atModeAttributes }); +/** + * @param browserAttributes - Browser attributes + * @returns {{association: string, attributes: string[]}} + */ +const browserAssociation = browserAttributes => ({ + association: 'browsers', + attributes: browserAttributes +}); + // At /** @@ -45,6 +55,7 @@ const atModeAssociation = atModeAttributes => ({ * @param {string[]} atAttributes - At attributes to be returned in the result * @param {string[]} atVersionAttributes - AtVersion attributes to be returned in the result * @param {string[]} atModeAttributes - AtMode attributes to be returned in the result + * @param {string[]} browserAttributes - Browser attributes to be returned in the result * @param {object} options - Generic options for Sequelize * @param {*} options.transaction - Sequelize transaction * @returns {Promise<*>} @@ -54,6 +65,7 @@ const getAtById = async ( atAttributes = AT_ATTRIBUTES, atVersionAttributes = AT_VERSION_ATTRIBUTES, atModeAttributes = AT_MODE_ATTRIBUTES, + browserAttributes = BROWSER_ATTRIBUTES, options = {} ) => { return ModelService.getById( @@ -62,7 +74,8 @@ const getAtById = async ( atAttributes, [ atVersionAssociation(atVersionAttributes), - atModeAssociation(atModeAttributes) + atModeAssociation(atModeAttributes), + browserAssociation(browserAttributes) ], options ); @@ -74,6 +87,7 @@ const getAtById = async ( * @param {string[]} atAttributes - At attributes to be returned in the result * @param {string[]} atVersionAttributes - AtVersion attributes to be returned in the result * @param {string[]} atModeAttributes - AtMode attributes to be returned in the result + * @param {string[]} browserAttributes - Browser attributes to be returned in the result * @param {object} pagination - pagination options for query * @param {number} [pagination.page=0] - page to be queried in the pagination result (affected by {@param pagination.enablePagination}) * @param {number} [pagination.limit=10] - amount of results to be returned per page (affected by {@param pagination.enablePagination}) @@ -89,6 +103,7 @@ const getAts = async ( atAttributes = AT_ATTRIBUTES, atVersionAttributes = AT_VERSION_ATTRIBUTES, atModeAttributes = AT_MODE_ATTRIBUTES, + browserAttributes = BROWSER_ATTRIBUTES, pagination = {}, options = {} ) => { @@ -103,7 +118,8 @@ const getAts = async ( atAttributes, [ atVersionAssociation(atVersionAttributes), - atModeAssociation(atModeAttributes) + atModeAssociation(atModeAttributes), + browserAssociation(browserAttributes) ], pagination, options @@ -115,6 +131,7 @@ const getAts = async ( * @param {string[]} atAttributes - At attributes to be returned in the result * @param {string[]} atVersionAttributes - AtVersion attributes to be returned in the result * @param {string[]} atModeAttributes - AtMode attributes to be returned in the result + * @param {string[]} browserAttributes - Browser attributes to be returned in the result * @param {object} options - Generic options for Sequelize * @param {*} options.transaction - Sequelize transaction * @returns {Promise<*>} @@ -124,6 +141,7 @@ const createAt = async ( atAttributes = AT_ATTRIBUTES, atVersionAttributes = AT_VERSION_ATTRIBUTES, atModeAttributes = AT_MODE_ATTRIBUTES, + browserAttributes = BROWSER_ATTRIBUTES, options = {} ) => { const atResult = await ModelService.create(At, { name }); @@ -136,7 +154,8 @@ const createAt = async ( atAttributes, [ atVersionAssociation(atVersionAttributes), - atModeAssociation(atModeAttributes) + atModeAssociation(atModeAttributes), + browserAssociation(browserAttributes) ], options ); @@ -148,6 +167,7 @@ const createAt = async ( * @param {string[]} atAttributes - At attributes to be returned in the result * @param {string[]} atVersionAttributes - AtVersion attributes to be returned in the result * @param {string[]} atModeAttributes - AtMode attributes to be returned in the result + * @param {string[]} browserAttributes - Browser attributes to be returned in the result * @param {object} options - Generic options for Sequelize * @param {*} options.transaction - Sequelize transaction * @returns {Promise<*>} @@ -158,6 +178,7 @@ const updateAt = async ( atAttributes = AT_ATTRIBUTES, atVersionAttributes = AT_VERSION_ATTRIBUTES, atModeAttributes = AT_MODE_ATTRIBUTES, + browserAttributes = BROWSER_ATTRIBUTES, options = {} ) => { await ModelService.update(At, { id }, { name }, options); @@ -168,7 +189,8 @@ const updateAt = async ( atAttributes, [ atVersionAssociation(atVersionAttributes), - atModeAssociation(atModeAttributes) + atModeAssociation(atModeAttributes), + browserAssociation(browserAttributes) ], options ); diff --git a/server/models/services/BrowserService.js b/server/models/services/BrowserService.js index e23f3bf0c..64af2b07c 100644 --- a/server/models/services/BrowserService.js +++ b/server/models/services/BrowserService.js @@ -1,5 +1,9 @@ const ModelService = require('./ModelService'); -const { BROWSER_ATTRIBUTES, BROWSER_VERSION_ATTRIBUTES } = require('./helpers'); +const { + BROWSER_ATTRIBUTES, + BROWSER_VERSION_ATTRIBUTES, + AT_ATTRIBUTES +} = require('./helpers'); const { Sequelize, Browser, BrowserVersion } = require('../'); const { Op } = Sequelize; @@ -23,6 +27,15 @@ const browserVersionAssociation = browserVersionAttributes => ({ attributes: browserVersionAttributes }); +/** + * @param atAttributes - At attributes + * @returns {{association: string, attributes: string[]}} + */ +const atAssociation = atAttributes => ({ + association: 'ats', + attributes: atAttributes +}); + // Browser /** @@ -30,6 +43,7 @@ const browserVersionAssociation = browserVersionAttributes => ({ * @param {number} id - unique id of the Browser model being queried * @param {string[]} browserAttributes - Browser attributes to be returned in the result * @param {string[]} browserVersionAttributes - BrowserVersion attributes to be returned in the result + * @param {string[]} atAttributes - At attributes to be returned in the result * @param {object} options - Generic options for Sequelize * @param {*} options.transaction - Sequelize transaction * @returns {Promise<*>} @@ -38,13 +52,17 @@ const getBrowserById = async ( id, browserAttributes = BROWSER_ATTRIBUTES, browserVersionAttributes = BROWSER_VERSION_ATTRIBUTES, + atAttributes = AT_ATTRIBUTES, options = {} ) => { return ModelService.getById( Browser, id, browserAttributes, - [browserVersionAssociation(browserVersionAttributes)], + [ + browserVersionAssociation(browserVersionAttributes), + atAssociation(atAttributes) + ], options ); }; @@ -54,6 +72,7 @@ const getBrowserById = async ( * @param {object} filter - use this define conditions to be passed to Sequelize's where clause * @param {string[]} browserAttributes - Browser attributes to be returned in the result * @param {string[]} browserVersionAttributes - BrowserVersion attributes to be returned in the result + * @param {string[]} atAttributes - At attributes to be returned in the result * @param {object} pagination - pagination options for query * @param {number} [pagination.page=0] - page to be queried in the pagination result (affected by {@param pagination.enablePagination}) * @param {number} [pagination.limit=10] - amount of results to be returned per page (affected by {@param pagination.enablePagination}) @@ -68,6 +87,7 @@ const getBrowsers = async ( filter = {}, browserAttributes = BROWSER_ATTRIBUTES, browserVersionAttributes = BROWSER_VERSION_ATTRIBUTES, + atAttributes = AT_ATTRIBUTES, pagination = {}, options = {} ) => { @@ -80,7 +100,10 @@ const getBrowsers = async ( Browser, where, browserAttributes, - [browserVersionAssociation(browserVersionAttributes)], + [ + browserVersionAssociation(browserVersionAttributes), + atAssociation(atAttributes) + ], pagination, options ); @@ -90,6 +113,7 @@ const getBrowsers = async ( * @param {object} createParams - values to be used to create the Browser record * @param {string[]} browserAttributes - Browser attributes to be returned in the result * @param {string[]} browserVersionAttributes - BrowserVersion attributes to be returned in the result + * @param {string[]} atAttributes - At attributes to be returned in the result * @param {object} options - Generic options for Sequelize * @param {*} options.transaction - Sequelize transaction * @returns {Promise<*>} @@ -98,6 +122,7 @@ const createBrowser = async ( { name }, browserAttributes = BROWSER_ATTRIBUTES, browserVersionAttributes = BROWSER_VERSION_ATTRIBUTES, + atAttributes = AT_ATTRIBUTES, options = {} ) => { const browserResult = await ModelService.create(Browser, { name }, options); @@ -108,7 +133,10 @@ const createBrowser = async ( Browser, id, browserAttributes, - [browserVersionAssociation(browserVersionAttributes)], + [ + browserVersionAssociation(browserVersionAttributes), + atAssociation(atAttributes) + ], options ); }; @@ -118,6 +146,7 @@ const createBrowser = async ( * @param {object} updateParams - values to be used to update columns for the record being referenced for {@param id} * @param {string[]} browserAttributes - Browser attributes to be returned in the result * @param {string[]} browserVersionAttributes - BrowserVersion attributes to be returned in the result + * @param {string[]} atAttributes - At attributes to be returned in the result * @param {object} options - Generic options for Sequelize * @param {*} options.transaction - Sequelize transaction * @returns {Promise<*>} @@ -127,6 +156,7 @@ const updateBrowser = async ( { name }, browserAttributes = BROWSER_ATTRIBUTES, browserVersionAttributes = BROWSER_VERSION_ATTRIBUTES, + atAttributes = AT_ATTRIBUTES, options = {} ) => { await ModelService.update(Browser, { id }, { name }, options); @@ -135,7 +165,10 @@ const updateBrowser = async ( Browser, id, browserAttributes, - [browserVersionAssociation(browserVersionAttributes)], + [ + browserVersionAssociation(browserVersionAttributes), + atAssociation(atAttributes) + ], options ); }; diff --git a/server/resolvers/atsResolver.js b/server/resolvers/atsResolver.js index f0e51fe56..9dc381527 100644 --- a/server/resolvers/atsResolver.js +++ b/server/resolvers/atsResolver.js @@ -7,6 +7,7 @@ const atsResolver = async () => { undefined, undefined, undefined, + undefined, { order: [['name', 'asc']] } diff --git a/server/resolvers/browsersResolver.js b/server/resolvers/browsersResolver.js index 095b565d8..3ebe6ae78 100644 --- a/server/resolvers/browsersResolver.js +++ b/server/resolvers/browsersResolver.js @@ -1,7 +1,7 @@ const { getBrowsers } = require('../models/services/BrowserService'); const browsersResolver = () => { - return getBrowsers(undefined, undefined, undefined, undefined, { + return getBrowsers(undefined, undefined, undefined, undefined, undefined, { order: [['name', 'asc']] }); }; diff --git a/server/seeders/20230622202911-addAtBrowser.js b/server/seeders/20230622202911-addAtBrowser.js new file mode 100644 index 000000000..4da59f308 --- /dev/null +++ b/server/seeders/20230622202911-addAtBrowser.js @@ -0,0 +1,34 @@ +'use strict'; + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable('AtBrowsers', { + atId: { type: Sequelize.DataTypes.INTEGER }, + browserId: { type: Sequelize.DataTypes.INTEGER } + }); + const jawsAtId = 1; + const nvdaAtId = 2; + const voiceOverAtId = 3; + + const firefoxBrowserId = 1; + const chromeBrowserId = 2; + const safariBrowserId = 3; + return queryInterface.bulkInsert( + 'AtBrowsers', + [ + { atId: jawsAtId, browserId: firefoxBrowserId }, + { atId: jawsAtId, browserId: chromeBrowserId }, + { atId: nvdaAtId, browserId: firefoxBrowserId }, + { atId: nvdaAtId, browserId: chromeBrowserId }, + { atId: voiceOverAtId, browserId: safariBrowserId }, + { atId: voiceOverAtId, browserId: firefoxBrowserId }, + { atId: voiceOverAtId, browserId: chromeBrowserId } + ], + {} + ); + }, + + down: async (queryInterface /* , Sequelize */) => { + await queryInterface.dropTable('AtBrowsers'); + } +}; diff --git a/server/tests/integration/graphql.test.js b/server/tests/integration/graphql.test.js index c632232eb..b5a39d68b 100644 --- a/server/tests/integration/graphql.test.js +++ b/server/tests/integration/graphql.test.js @@ -177,6 +177,11 @@ describe('graphql', () => { __typename id name + ats { + __typename + id + name + } browserVersions { __typename id @@ -187,6 +192,11 @@ describe('graphql', () => { __typename id name + browsers { + __typename + id + name + } atVersions { __typename id diff --git a/server/tests/models/services/AtService.test.js b/server/tests/models/services/AtService.test.js index 62d126c58..b20509f0e 100644 --- a/server/tests/models/services/AtService.test.js +++ b/server/tests/models/services/AtService.test.js @@ -26,6 +26,7 @@ describe('AtModel Data Checks', () => { ); expect(at).toHaveProperty('atVersions'); expect(at).toHaveProperty('modes'); + expect(at).toHaveProperty('browsers'); }); it('should return valid at for id query with no associations', async () => { @@ -33,7 +34,7 @@ describe('AtModel Data Checks', () => { const _id = 1; // A2 - const at = await AtService.getAtById(_id, null, [], []); + const at = await AtService.getAtById(_id, null, [], [], []); const { id, name } = at; // A3 @@ -46,6 +47,7 @@ describe('AtModel Data Checks', () => { ); expect(at).not.toHaveProperty('atVersions'); expect(at).not.toHaveProperty('modes'); + expect(at).not.toHaveProperty('browsers'); }); it('should not be valid at query', async () => { @@ -85,6 +87,19 @@ describe('AtModel Data Checks', () => { expect(modes.length).toBeGreaterThanOrEqual(1); }); + it('should contain valid at with browsers array', async () => { + // A1 + const _id = 1; + + // A2 + const at = await AtService.getAtById(_id); + const { browsers } = at; + + // A3 + expect(browsers).toBeInstanceOf(Array); + expect(browsers.length).toBeGreaterThanOrEqual(1); + }); + it('should create and remove a new at', async () => { await dbCleaner(async () => { // A1 @@ -160,7 +175,8 @@ describe('AtModel Data Checks', () => { id: expect.any(Number), name: expect.any(String), atVersions: expect.any(Array), - modes: expect.any(Array) + modes: expect.any(Array), + browsers: expect.any(Array) }) ]) ); @@ -182,7 +198,8 @@ describe('AtModel Data Checks', () => { id: expect.any(Number), name: expect.stringMatching(/nvd/gi), atVersions: expect.any(Array), - modes: expect.any(Array) + modes: expect.any(Array), + browsers: expect.any(Array) }) ]) ); @@ -190,7 +207,7 @@ describe('AtModel Data Checks', () => { it('should return collection of ats with paginated structure', async () => { // A1 - const result = await AtService.getAts('', {}, ['name'], [], [], { + const result = await AtService.getAts('', {}, ['name'], [], [], [], { enablePagination: true }); diff --git a/server/tests/models/services/BrowserService.test.js b/server/tests/models/services/BrowserService.test.js index ba29bd2d8..335d7c413 100644 --- a/server/tests/models/services/BrowserService.test.js +++ b/server/tests/models/services/BrowserService.test.js @@ -25,6 +25,7 @@ describe('BrowserModel Data Checks', () => { }) ); expect(browser).toHaveProperty('browserVersions'); + expect(browser).toHaveProperty('ats'); }); it('should return valid browser for id query with no associations', async () => { @@ -32,7 +33,7 @@ describe('BrowserModel Data Checks', () => { const _id = 1; // A2 - const browser = await BrowserService.getBrowserById(_id, null, []); + const browser = await BrowserService.getBrowserById(_id, null, [], []); const { id, name } = browser; // A3 @@ -44,6 +45,7 @@ describe('BrowserModel Data Checks', () => { }) ); expect(browser).not.toHaveProperty('browserVersions'); + expect(browser).not.toHaveProperty('ats'); }); it('should not be valid browser query', async () => { @@ -70,6 +72,19 @@ describe('BrowserModel Data Checks', () => { expect(browserVersions.length).toBeGreaterThanOrEqual(1); }); + it('should contain valid browser with ats array', async () => { + // A1 + const _id = 1; + + // A2 + const browser = await BrowserService.getBrowserById(_id); + const { ats } = browser; + + // A3 + expect(ats).toBeInstanceOf(Array); + expect(ats.length).toBeGreaterThanOrEqual(1); + }); + it('should create and remove a new browser', async () => { await dbCleaner(async () => { // A1 @@ -144,7 +159,8 @@ describe('BrowserModel Data Checks', () => { expect.objectContaining({ id: expect.any(Number), name: expect.any(String), - browserVersions: expect.any(Array) + browserVersions: expect.any(Array), + ats: expect.any(Array) }) ]) ); @@ -165,7 +181,8 @@ describe('BrowserModel Data Checks', () => { expect.objectContaining({ id: expect.any(Number), name: expect.stringMatching(/chr/gi), - browserVersions: expect.any(Array) + browserVersions: expect.any(Array), + ats: expect.any(Array) }) ]) ); @@ -173,9 +190,16 @@ describe('BrowserModel Data Checks', () => { it('should return collection of browsers with paginated structure', async () => { // A1 - const result = await BrowserService.getBrowsers('', {}, ['name'], [], { - enablePagination: true - }); + const result = await BrowserService.getBrowsers( + '', + {}, + ['name'], + [], + [], + { + enablePagination: true + } + ); // A3 expect(result.data.length).toBeGreaterThanOrEqual(1); From ec2bf96a27c3bf68e202e1f6c15c0c8c5ee869f0 Mon Sep 17 00:00:00 2001 From: Paul Clue <67766160+Paul-Clue@users.noreply.github.com> Date: Mon, 24 Jul 2023 16:05:51 -0500 Subject: [PATCH 2/2] Remove comment and create migration --- server/apps/embed.js | 2 -- .../migrations/20230724205435-addAtBrowser.js | 29 +++++++++++++++++++ server/seeders/20230622202911-addAtBrowser.js | 6 +--- 3 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 server/migrations/20230724205435-addAtBrowser.js diff --git a/server/apps/embed.js b/server/apps/embed.js index ccdda3a28..c4b9b3cf9 100644 --- a/server/apps/embed.js +++ b/server/apps/embed.js @@ -32,8 +32,6 @@ app.set('views', resolve(handlebarsPath, 'views')); // stale data for however long it takes for the query to complete. const millisecondsUntilStale = 5000; -// TODO: Provide through resolvers - const queryReports = async () => { const { data, errors } = await apolloServer.executeOperation({ query: gql` diff --git a/server/migrations/20230724205435-addAtBrowser.js b/server/migrations/20230724205435-addAtBrowser.js new file mode 100644 index 000000000..8c39716cc --- /dev/null +++ b/server/migrations/20230724205435-addAtBrowser.js @@ -0,0 +1,29 @@ +'use strict'; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable('AtBrowsers', { + atId: { + type: Sequelize.DataTypes.INTEGER, + allowNull: false, + references: { + model: 'At', + key: 'id' + } + }, + browserId: { + type: Sequelize.DataTypes.INTEGER, + allowNull: false, + references: { + model: 'Browser', + key: 'id' + } + } + }); + }, + + down: async (queryInterface /* , Sequelize */) => { + await queryInterface.dropTable('AtBrowsers'); + } +}; diff --git a/server/seeders/20230622202911-addAtBrowser.js b/server/seeders/20230622202911-addAtBrowser.js index 4da59f308..9faa06cb9 100644 --- a/server/seeders/20230622202911-addAtBrowser.js +++ b/server/seeders/20230622202911-addAtBrowser.js @@ -1,11 +1,7 @@ 'use strict'; module.exports = { - up: async (queryInterface, Sequelize) => { - await queryInterface.createTable('AtBrowsers', { - atId: { type: Sequelize.DataTypes.INTEGER }, - browserId: { type: Sequelize.DataTypes.INTEGER } - }); + up: async (queryInterface /* , Sequelize */) => { const jawsAtId = 1; const nvdaAtId = 2; const voiceOverAtId = 3;