diff --git a/nextjs-app/__tests__/components/SchoolRow.test.tsx b/nextjs-app/__tests__/components/SchoolRow.test.tsx
new file mode 100644
index 0000000..dcdab0e
--- /dev/null
+++ b/nextjs-app/__tests__/components/SchoolRow.test.tsx
@@ -0,0 +1,36 @@
+/**
+ * SchoolRow (primary search results): line 2 prints the religious character
+ * only when the school has one. The register's "None" was printed as a chip.
+ */
+
+import '@testing-library/jest-dom';
+import { render, screen } from '@testing-library/react';
+import { SchoolRow } from '@/components/SchoolRow';
+import type { School } from '@/lib/types';
+
+const base = {
+ urn: 100001,
+ school_name: 'Alpha Primary School',
+ local_authority: 'Testshire',
+ school_type: 'Free schools',
+ phase: 'Primary',
+ gender: 'Mixed',
+ age_range: '4-11',
+ rwm_expected_pct: 70,
+} as unknown as School;
+
+describe('SchoolRow religious character', () => {
+ it.each(['None', 'Does not apply', ''])(
+ 'prints nothing when the register says %p',
+ (religious_denomination) => {
+ render();
+ expect(screen.queryByText('None')).not.toBeInTheDocument();
+ expect(screen.queryByText('Does not apply')).not.toBeInTheDocument();
+ },
+ );
+
+ it('prints a religious character the school has', () => {
+ render();
+ expect(screen.getByText('Church of England')).toBeInTheDocument();
+ });
+});
diff --git a/nextjs-app/__tests__/components/SecondarySchoolRow.test.tsx b/nextjs-app/__tests__/components/SecondarySchoolRow.test.tsx
index a868256..e3a25ac 100644
--- a/nextjs-app/__tests__/components/SecondarySchoolRow.test.tsx
+++ b/nextjs-app/__tests__/components/SecondarySchoolRow.test.tsx
@@ -65,3 +65,38 @@ describe('SecondarySchoolRow proposed-to-close tag', () => {
expect(screen.queryByText(/Proposed to close/)).not.toBeInTheDocument();
});
});
+
+describe('SecondarySchoolRow admissions tag', () => {
+ it('tags a selective school', () => {
+ render();
+ expect(screen.getByText('Selective')).toBeInTheDocument();
+ });
+
+ it('does not tag a non-selective school as selective', () => {
+ // "Non-selective" contains "selective": a substring test tagged every
+ // comprehensive (Burntwood, Graveney) as Selective.
+ render();
+ expect(screen.queryByText('Selective')).not.toBeInTheDocument();
+ });
+
+ it.each(['None', 'Does not apply', '', null])(
+ 'gives no faith tag when the religious character is %p',
+ (religious_denomination) => {
+ render(
+ ,
+ );
+ expect(screen.queryByText('Faith priority')).not.toBeInTheDocument();
+ },
+ );
+
+ it('tags a school with a religious character', () => {
+ render(
+ ,
+ );
+ expect(screen.getByText('Faith priority')).toBeInTheDocument();
+ });
+});
diff --git a/nextjs-app/components/SchoolRow.tsx b/nextjs-app/components/SchoolRow.tsx
index 306363a..fe167b0 100644
--- a/nextjs-app/components/SchoolRow.tsx
+++ b/nextjs-app/components/SchoolRow.tsx
@@ -9,7 +9,7 @@
*/
import type { School } from '@/lib/types';
-import { formatPercentage, calculateTrend, getPhaseStyle, schoolUrl, buildOfstedListBadge, formatAgeRange, isProposedToClose, isSpecialSchool, listRwmValue } from '@/lib/utils';
+import { formatPercentage, calculateTrend, getPhaseStyle, schoolUrl, buildOfstedListBadge, formatAgeRange, hasReligiousCharacter, isProposedToClose, isSpecialSchool, listRwmValue } from '@/lib/utils';
import styles from './SchoolRow.module.css';
interface SchoolRowProps {
@@ -34,9 +34,7 @@ export function SchoolRow({
const ofstedBadge = buildOfstedListBadge(school);
const showGender = school.gender && school.gender.toLowerCase() !== 'mixed';
- const showDenomination =
- school.religious_denomination &&
- school.religious_denomination !== 'Does not apply';
+ const showDenomination = hasReligiousCharacter(school.religious_denomination);
// The school's OWN figure and its year-over-year trend are same-school
// measures — shown whenever there's a real value (not the all-zero
diff --git a/nextjs-app/components/SecondarySchoolRow.tsx b/nextjs-app/components/SecondarySchoolRow.tsx
index e10ca0a..762937d 100644
--- a/nextjs-app/components/SecondarySchoolRow.tsx
+++ b/nextjs-app/components/SecondarySchoolRow.tsx
@@ -11,14 +11,14 @@
'use client';
import type { School } from '@/lib/types';
-import { buildOfstedListBadge, getPhaseStyle, schoolUrl, formatAgeRange, isProposedToClose, isSpecialSchool } from '@/lib/utils';
+import { buildOfstedListBadge, getPhaseStyle, schoolUrl, formatAgeRange, hasReligiousCharacter, isProposedToClose, isSpecialSchool } from '@/lib/utils';
import styles from './SecondarySchoolRow.module.css';
function detectAdmissionsTag(school: School): string | null {
- const policy = school.admissions_policy?.toLowerCase() ?? '';
- if (policy.includes('selective')) return 'Selective';
- const denom = school.religious_denomination ?? '';
- if (denom && denom !== 'Does not apply') return 'Faith priority';
+ // Exact match: "Non-selective" contains "selective", so a substring test
+ // tagged every comprehensive as Selective.
+ if (school.admissions_policy?.trim().toLowerCase() === 'selective') return 'Selective';
+ if (hasReligiousCharacter(school.religious_denomination)) return 'Faith priority';
return null;
}
diff --git a/nextjs-app/lib/utils.ts b/nextjs-app/lib/utils.ts
index 3422edb..09a76c4 100644
--- a/nextjs-app/lib/utils.ts
+++ b/nextjs-app/lib/utils.ts
@@ -902,6 +902,15 @@ export function isSpecialSchool(school: { school_type?: string | null }): boolea
return /\bspecial\b/.test(t) || /pupil referral/.test(t) || /alternative provision/.test(t);
}
+/**
+ * Whether GIAS records a religious character. "None" and "Does not apply" are
+ * the register's two ways of saying it has none, and neither is a faith.
+ */
+export function hasReligiousCharacter(value: string | null | undefined): boolean {
+ const v = value?.trim().toLowerCase() ?? '';
+ return v !== '' && v !== 'none' && v !== 'does not apply';
+}
+
/**
* The school's combined Reading, Writing & Maths figure, or null when there is
* no real one to show.